I found this page where there is an example for extract cell information from an Insight-Explorer but... what about to write into the cell from a c# application?
C# extract Cell Information from In-Sight Explorer (Cognex)
If you want to control the cells in the current job file of an In-Sight camera using C#, here is the method that has worked for me. Please note, I'm using In-Sight Explorer v5.9.0, but I've tested this on earlier versions too and it still works.
NOTE: Without a Cognex In-Sight SDK license, you will not be able to run this application within Visual Studio. You will have to build the project and then run the executable directly.
Open Visual Studio
Create a new Console App (.NET Framework) project
I'm using .NET Framework 4.7.2
Right-click on the project in the solution explorer and add a reference to the Cognex.InSight.dll file (It is typically located here: C:\Program Files (x86)\Common Files\Cognex\In-Sight\5.x.x.x\Cognex.InSight.dll)
Set the target platform to x86
Paste the code, below, into your project
Change the username, password and ipAddress variables to match what's setup for your camera
Build
Go to the Debug folder and find the executable that was created after building the project
Double-click the executable to run it
using System;
using Cognex.InSight;
namespace ChangeInSightCellValue2
{
class Program
{
static void Main(string[] args)
{
string username = "admin";
string password = "";
string ipAddress = "127.0.0.1";
// Create camera object and connect to it
CvsInSight camera = LogIntoCamera(ipAddress, username, password, true, false);
// Define which cell you want to modify
CvsCellLocation cell = new CvsCellLocation(2, 'C');
// Modify the cell expression
camera.SetExpression(cell, "Filter($A$0,0,0,0,80,100,320,440,0,0,3,3,1,128,128,128,1,1,0)", true);
}
// Log into camera
private static CvsInSight LogIntoCamera(string sCamIP, string sCamUsername, string sCamPassword, bool forceConnect, bool connectAsynchronous)
{
// Create camera object
CvsInSight insight = new CvsInSight();
Console.WriteLine("Object created");
IAsyncResult result;
// Try logging into the camera on a different thread to prevent locking this one up
Action action = () =>
{
// Connect to camera
insight.Connect(sCamIP, sCamUsername, sCamPassword, forceConnect, connectAsynchronous);
};
result = action.BeginInvoke(null, null);
if (result.AsyncWaitHandle.WaitOne(5000))
return insight;
else
return insight;
}
}
}
NOTE: If you're connected to the camera with In-Sight Explorer when you run this application, the In-Sight Explorer will disconnect from the camera and then try to reconnect after your application has disconnected from the camera.
You could use Native Mode Commands to set the value of controls in the spreadsheet in In-Sight Explorer (as discussed in the question you linked to). Note that you won't be able to write data to any cell - you will only be able to write to cells containing EditInt(), EditFloat(), EditString(), CheckBox(), etc functions. Send the commands as text over a socket connection to the cameras port 23. You will need to send a username and password to the camera when the connection is established.
If you're using the Cognex SDK, use the following functions
CvsInSight.SetFloat(...) to set EditFloat control values
CvsInSight.SetInteger(...) to set EditInt control values
CvsInSight.SetListBoxIndex(...) to select items in list boxes
CvsInSight.SetString(...) to set EditString control values
CvsInSight.SetCheckBox(...) to change the state of CheckBox controls
Related
We have a desktop Windows app (written in WFP/C#) that we distribute as a single .exe file with no installer (it bundles all its dependencies via a Fody/Costura plugin).
We would like to integrate a local Action Center toast functionality where the app can display a toast and respond to it when it's clicked.
Displaying the toast is straightforward and can be done by using the Microsoft.Toolkit.Uwp.Notifications nuget package. However, in order to actually receive proper notifications when the toast is clicked in the Action Center (as opposed to the balloon tip) we need to register with notification platform.
The guide on how to do this seems to be focused on apps with an installer (e.g. Wix): https://learn.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/send-local-toast-desktop?fbclid=IwAR2AoHRKI88VNGRG-pTUytwhkMuovWT4bEr0RoXEayWpWsoGlghtZeq4Mo4#step-4-register-with-notification-platform
The specific task we're trying to achieve is, from the documentation:
If you're using classic Win32 (or if you support both), you have to declare your Application User Model ID (AUMID) and toast activator CLSID (the GUID from step #3) on your app's shortcut in Start.
How can we do it without writing an installer? We would like our app to do this registration on first run.
Note: the app already has provisions for elevating itself through UAC if needed by restarting itself in Administrator context.
Additional references: WPF native windows 10 toasts
[Update]
I managed to follow the instructions in https://learn.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/send-local-toast-desktop
and https://learn.microsoft.com/en-us/windows/win32/shell/enable-desktop-toast-with-appusermodelid to put together what should have been a working solution, but in the end, clicking on toasts in the Action Center does not trigger OnActivated() in my NotificationActivatior.
Salient points:
Sending notification
var toast = new ToastNotification(toastXml);
DesktopNotificationManagerCompat.CreateToastNotifier().Show(toast);
Registration:
string shortcutPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.Programs),
"Toasty.lnk");
DesktopNotificationManagerCompat.RegisterAumidAndComServer
<MyNotificationActivator>(AppName);
DesktopNotificationManagerCompat.RegisterActivator
<MyNotificationActivator>();
if (!File.Exists(shortcutPath))
{
ShortcutManager.RegisterAppForNotifications(
shortcutPath,
Assembly.GetExecutingAssembly().Location,
null,
AppName,
ActivationId);
}
Creating a shortcut
public static void RegisterAppForNotifications(
string shortcutPath,
string appExecutablePath,
string arguments,
string appName,
string activatorId)
{
var shellLinkClass = new ShellLinkCoClass();
IShellLinkW shellLink = (IShellLinkW)shellLinkClass;
shellLink.SetPath(appExecutablePath);
IPropertyStore propertyStore = (IPropertyStore)shellLinkClass;
IPersistFile persistFile = (IPersistFile)shellLinkClass;
if (arguments != null)
{
shellLink.SetArguments(arguments);
}
// https://learn.microsoft.com/en-us/windows/win32/properties/props-system-appusermodel-id
propertyStore.SetValue(
new PropertyKey("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3", 5),
new PROPVARIANT(appName));
// https://learn.microsoft.com/en-us/windows/win32/properties/props-system-appusermodel-toastactivatorclsid
propertyStore.SetValue(
new PropertyKey("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3", 26),
new PROPVARIANT(new Guid(activatorId)));
propertyStore.Commit();
persistFile.Save(shortcutPath, true);
}
[Update]
Finally got it to work - not sure what was wrong before, but the final version seems to be okay. Full code: https://gist.github.com/davidair/c4ea207bf6eece4ef08b97ab29a3036f
I have the same problem with my project now.
Managed to find this repository - https://github.com/felixrieseberg/electron-windows-interactive-notifications
Here's C++ implementation for installing shortcut (InteractiveNotifications file, InstallShortcut method). I guess the problem is how we set the value to PropertyStore, string GUID is not suitable for some reason. Still, I wasn't able to solve the problem for now.
UPDATED: Finally, was able to install shortcut from code! Check my example at Github. https://github.com/romayavorskyi/WpfNotificationTest (still a lot of hardcode, but it should give you the general idea). And you were right, shortcut path matters. It seems shortcut should be in the ProgramData folder for correct work.
We are develop a windows service for open a specific port.
Now this port can be custom for the user during the installation in a dialog.
I want know a possibility of capture this value and pass to the code of the service
if (myServer == null)
{
int port= int.Parse(ConfigurationManager.AppSettings["port1"]);
myServer = new NHttp.HttpServer
{
EndPoint = new System.Net.IPEndPoint(0, port)
};
}
myServer.Start();
I try using a value in app.config and editing this value in the installer:
public override void Install(System.Collections.IDictionary stateSaver)
{
string portServer= this.Context.Parameters["CTPUERTO"];
System.Configuration.ConfigurationManager.AppSettings.Set("port1", portServer);
base.Install(stateSaver);
}
CTPUERTO is the name of the textbox in the dialog install
You add the optional TextBoxes(A) dialog to your setup project and the user enters that text (in EDITA1 in the docs):
https://msdn.microsoft.com/en-us/library/e04k6f53(v=vs.100).aspx
Then in your custom action you'd add the parameter with something like:
/port1=[EDITA1]
in CustomActionData, then access it using the kind of code you showed, in an installer class.
These might be useful:
.net Setup Project: How to pass multiple CustomActionData fields
https://www.codeproject.com/Articles/12780/A-Setup-and-Deployment-project-that-passes-paramet
The main issue with this (because of the way VS setup projects work) is that you cannot validate it at the time it's entered. Custom actions in VS setup projects run after the UI and after everything is installed, so if your custom finds it's incorrect then you fail the whole install and roll back.
How can I get the number of times a program has previously run in c# without keeping a file and tallying. Is there a Application class or something in c# to check the count.
Please give a detailed explantion as i know nothing about it.This is A windows console application not windows forms.
You can do that my creating an Entry in the Registry. And another way is by using an Application Settings.
But I prefer Application Settings because it has less task to do.
See HERE: Creating an Application Settings.
Tutorial From Youtube
Recent versions of Windows automatically maintain this information in the registry under HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist.
The data is obfuscated with ROT13, but that's easy to "decrypt". A free utility (with source code) is available and can serve as your starting point.
You could send a message to a database or webservice every time the program starts up (assuming there's a network connection).
You could keep a count on some form of hardware thet's not a standard storage device (therefore not technically being a file).
You could make a registry entry that you keep the count in (if you ignore the fact that the registry entry is, at some level, persisted into a file somewhere).
You could just have a file somewhere that keeps track of the count. Not sure why you're so opposed to this one in the first place....
If you are running a Winforms application, the you can easily use the Application Settings. Right click on your Solution Name --> Properties --> Settings Tab. More info and tutorial here.
Then, every time your program starts, increment this setting and save it.
Ref: Count the number of times the Program has been launched
In my knowledge Windows does not keep this information for you. You would have to tally the value somewhere (file, database, registry setting).
Better way is Application Settings as:
Create setting in app.config and then use it as:
Properties.Settings.Default.FirstUserSetting = "abc";
then, you usually do this in the Closing event handler of the main form. The following statement to Save settings method.
Properties.Settings.Default.Save();
Implementation using Registry:
static string AppRegyPath = "Software\\Cheeso\\ApplicationName";
static string rvn_Runs = "Runs";
private Microsoft.Win32.RegistryKey _appCuKey;
public Microsoft.Win32.RegistryKey AppCuKey
{
get
{
if (_appCuKey == null)
{
_appCuKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(AppRegyPath, true);
if (_appCuKey == null)
_appCuKey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(AppRegyPath);
}
return _appCuKey;
}
set { _appCuKey = null; }
}
public int UpdateRunCount()
{
int x = (Int32)AppCuKey.GetValue(rvn_Runs, 0);
x++;
AppCuKey.SetValue(rvn_Runs, x);
return x;
}
If it's a WinForms app, you can hook the Form's OnClosing event to run UpdateCount.
Then Check tutorial to Read, write and delete from registry with C#
I am trying to create a little helper application, one scenario is "file duplication finder". What I want to do is this:
I start my C# .NET app, it gives me an empty list.
Start the normal windows explorer, select a file in some folder
The C# app tells me stuff about this file (e.g. duplicates)
How can I monitor the currently selected file in the "normal" windows explorer instance. Do I have to start the instance using .NET to have a handle of the process. Do I need a handle, or is there some "global hook" I can monitor inside C#. Its a little bit like monitoring the clipboard, but not exactly the same...
Any help is appreciated (if you don't have code, just point me to the right interops, dlls or help pages :-) Thanks, Chris
EDIT 1 (current source, thanks to Mattias)
using SHDocVw;
using Shell32;
public static void ListExplorerWindows()
{
foreach (InternetExplorer ie in new ShellWindowsClass())
DebugExplorerInstance(ie);
}
public static void DebugExplorerInstance(InternetExplorer instance)
{
Debug.WriteLine("DebugExplorerInstance ".PadRight(30, '='));
Debug.WriteLine("FullName " + instance.FullName);
Debug.WriteLine("AdressBar " + instance.AddressBar);
var doc = instance.Document as IShellFolderViewDual ;
if (doc != null)
{
Debug.WriteLine(doc.Folder.Title);
foreach (FolderItem item in doc.SelectedItems())
{
Debug.WriteLine(item.Path);
}
}
}
You can do this with the shell automation interfaces. The basic process is to
Run Tlbimp on Shdocwv.dll and
Shell32.dll (or directly add a
reference from VS).
Create an
instance of the ShellWindows
collection and iterate. This will
contain both Windows Explorer and
Internet Explorer windows.
For
Windows Explorer windows, the
IWebBrowser2.Document property will
return a IShellFolderViewDual
reference.
The IShellFolderViewDual
has a SelectedItems method you can
query and an event for changes you
can handle.
I am trying to develop a util (using system-hook) for that works like an expander (user selects some text and presses a hotkey and it is expands). It should work with Visual Studio.
I want to implement this using Windows API because I want to develop an app that works globally with any application (whether you're using VS, or wordpad, you should get the same functionality).
I've been able to do this successfully with notepad, wordpad, etc. using EM_ GETSEL and EM_REPLACESEL messages. But these APIs are not working with Visual Studio, or ms word.
What APIs should I use to be able to
1. Detect what text is selected.
2. Send input to the editor.
I am programming in C#. If you must know what I am trying to do... I am trying to make a universal port of ZenCoding that works on any editor. So all help will be appreciated.
For part 2 you could try using Windows Input Simulator which is an open source project I've just released to Codeplex to wrap the Win32 SendInput. Instead of SendKeys which just simulates text input, you can actually simulate real key strokes and complex chords to the active window.
In your case, if the user can perform the task with the Keyboard, this project will help you, otherwise you'd need to find another solution.
Hope this helps.
Why don't you use a System.Windows.Forms.SendKeys class for simulating keyboard input from user?
You can use:
SendKeys.SendWait("^C"); //CTRL+C
var selectedText = Clipboard.GetText();
var newText = Replace(selectedText);
SendKEys.SendWait("^V"); //CTRL+V
You can use WPF's Automation functionality, encapsulated in these two namespaces:
System.Windows.Automation
System.Windows.Automation.Provider
As an example, this is a method for finding an automation target element (e.g. a typical win control):
public static AutomationElement FindElement(AutomationElement context, PropertyCondition[] conditions)
{
// if no conditions, there's no search to do: just return the context, will be used as target
if (conditions == null)
{
return (context);
}
// create the condition to find
System.Windows.Automation.Condition condition = null;
if (conditions.Length <= 0)
{
throw (new ArgumentException("No conditions specified"));
}
else if (conditions.Length == 1)
{
condition = conditions[0];
}
else
{
AndCondition ac = new AndCondition(conditions);
condition = ac;
}
// find the element
CacheRequest creq = new CacheRequest();
creq.TreeFilter = Automation.ControlViewCondition;
using (creq.Activate())
{
AutomationElement e = AutomationContext(context);
AutomationElement target = e.FindFirst(TreeScope.Subtree, condition);
return (target);
}
}
Whatever you try, be absolutely sure to try it, ASAP, with Visual Studio 2010 beta 2. The editor has largely been rewritten, and hacks that work with an earlier version should be tested again.