I'm currently developing a windows service with c# and .net framework 4.5 to extend the functionality of an existing propietary application, this service blocks on an EventWaitHandleClass (msdn link) waiting for a named event signaled from the main application. Something like this:
bool boolWithFalse = false;
string eName = "notification_event";
string usr = Environment.UserDomainName + "\\" + Environment.UserName;
EventWaitHandleSecurity security = new EventWaitHandleSecurity(); //*
EventWaitHandleAccessRule rule = new EventWaitHandleAccessRule(usr, EventWaitHandleRights.Synchronize, AccessControlType.Allow);
security.AddAccessRule(rule);
EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.ManualReset, eName, out boolWithFalse, security);
//... some non relevant code lines here
//This is where the it locks waiting for the named event
var w = EventWaitHandle.WaitAny(new[] { handle }, Timeout.Infinite);
*: EventWaitHandleSecurity MSDN
Now this works like a charm if i execute my program as a console application, i can easily catch events from the main application and handle them as i intend, BUT, when i install the application as a service it locks waiting for this same named event but never receive the signal. The service is set to run using the NT AUTHORITY\LOCALSERVICE account, i've already tried using my own account (wich the progam uses while running as a console application) and yet nothing happens.
If it helps the application that originates the signal is running under my own account. I appreciate any help as i'm a complete beginner developing desktop applications for windows.
You got lost in the security hoopla. Two problems. The first one is that somebody has to create the event and somebody else has to open it so both components share the same event object. One of them has to use the EventWaitHandle constructor, the other has to call the EventWaitHandle.OpenExisting() method. The normal way is for the service to create the event and for the UI program to open it.
Next problem is the event object visibility. Windows implements namespaces for named operating system objects, pretty similar to how you use namespaces in the C# language. The root namespace is named by the session. And a service runs in a different session than the user's desktop programs. To get the desktop session program to see the event created in the service session, you have to use a "global" event name. Which looks like this:
string eName = "Global\\notification_event";
Do be careful of how you name your globally visible named event. There's another programmer somewhere someday that thinks that "notification_event" is a good choice for a name. You don't want to meet him. A {guid} is a good name, you get one from Tools + Create GUID. It is unique in the known universe, possibly beyond.
Related
link app with windows process so that when user terminated or end the process it says used by another process and also need to insert it into system file like shutdown file using c sharp so that my app never end or terminates
i tried that material but not usefull
this.ShowInTaskbar = false;
I also tried that code in click:
WindowsImpersonationContext ctx = null;
if (!WindowsIdentity.GetCurrent().IsSystem)
{
ctx = WindowsIdentity.Impersonate(System.IntPtr.Zero);
}
string thisuser = WindowsIdentity.GetCurrent().Name;
But have a look at image it is still present in process, what I want is that my process never stops.
what I want is that my process never stops.
To ensure that your process is always running and is started when Windows boots it's easiest to create a windows service instead. It will probably still show up somewhere in task manager and could be killed manually by the user. But windows will try to keep it running.
How to create a service:
https://msdn.microsoft.com/en-us/library/zt39148a(v=vs.110).aspx
And if you need other programs to communicate with your service I find it easy to use a WCF service instead.
https://msdn.microsoft.com/en-us/library/bb386386.aspx
I have an application that can be launched from the explorer context menu for a Windows drive. When you click the menu item the drive letter is passed to the new instance. I want to make sure that any old instance is closed.
I also want to make sure that the last drive that was selected is persisted, so that when I start the application again from the start-menu, it will remember the drive I originally selected.
It would be best if the already running application would receive an event so that it can update without having to kill and restart.
I tried the following, but that doesn't seem to be working:
This is my Class library method(it is just a line that define a variable so just i have a DLL that there a variable in it and no more)
namespace Dispatch
{
public class cls_get_drive_letter
{
public static string drive_letter;
}
}
This is my loading form code: (Here i will fill the DLL's variable)
private void Frm_loading_Load(object sender, EventArgs e)
{
Dispatch.cls_get_drive_letter.drive_letter = "XXX";
Process currentProcess = Process.GetCurrentProcess();
if (Process.GetProcessesByName(currentProcess.ProcessName, currentProcess.MachineName).Length >1)
{
currentProcess.Kill();
}
}
So when i run this for first time the "XXX" will be stored in DLL but when the current instance of application is running and i am going to run next instance of it the application will be closed because of this code:
Process currentProcess = Process.GetCurrentProcess();
if (Process.GetProcessesByName(currentProcess.ProcessName, currentProcess.MachineName).Length >1)
{
currentProcess.Kill();
}
So when closing code occurs with this code the new "XXX" will not stored in DLL and the last string will be in dll.
All variables, in this case a static field, will only remain the same for the running instance of your application.
When the application is started again the field is empty
A static variable is not stored 'inside a dll' but is stored inside the memory of the application that loads the dll. When a second instance of the application starts, it will have its own memory space and it will have its own version of the string variable. The variable is also not kept between instances, so as soon as you start a new instance it will have its own, empty string variable.
When the application is stopped, the memory for that instance is released and the variable is 'forgotten'.
If you want to share state between applications, there are all kinds of solutions, one could be the System.Configuration.Settings API, a file somewhere, a memory mapped file shared between multiple processes, a Named Pipe, a Kernel Semaphore. Options aplenty.
Until we understand exactly what it is you're trying to accomplish with this shared state, we can't provide you with a better alternative than the explanation that what you're doing right now, will not work do to the way static variables work.
Update based on new information:
You can store your currently selected drive in a Settings file for your project. You can add such file from the project properties in Visual Studio. There's a tab called settings. Create a new setting for "Selected Drive" and make it a User setting (that way you can update it without Admin rights).
To communicate a new drive letter to your already running application, you have a number of options.
For one, you could check whether your executable is already running (like you're doing now) and in that case update the settings file and exit the new instance. Your already running instance could periodically refresh the settings to pick up new values.
When your application starts, you can open a named pipe on your machine on which you listen for drive changes. When the 2nd instance starts, it can detect that the pipe is already there, write the new drive to the pipe and close. The already running application can pick up this message and change its configuration.
You can send a WindowMessage to the other application
You can host a simple WCF service to receive the notification
You can write the new drive letter to a file stored in a known location and have the other instance use a FileSystemWatcher to detect the changes to that file.
As I said the possibilities are endless.
If I were you I'd first make sure that the value is persisted between relaunches by implementing the Settings file in your application. Then investigate the options I described above, do some experimentation and then ask new questions when you cannot figure out how to make it work.
Can someone tell me what the InteractiveProcessRunner is for? Is it identical to Process.Start?
Here is the class.
And here an example :
InteractiveProcessRunner runner =
new InteractiveProcessRunner(notepad.exe,hSessionToken);
THX
Whit this class you can run a process with the complete environment of the user active: if you call this code from a service, you should find the user mapped resources, the desktop and all the resources that are available when the user is loggen on interactively even if launched from a service ie not logged interactively.
The source code to which your link leads referes to this article: http://asprosys.blogspot.com/2009/03/perils-and-pitfalls-of-launching.html which explains the motivation behind it.
Summary: You can't really use Process.Start() when you want to start a new process as certain user from a windows service. The InteractiveProcessRunner lets you do this (supposedly, never used it so I can't verify it). So it's not the same as Process.Start() - it uses a different Windows API.
I am having a situation like:
Suppose there is one folder "D:\Main" which can contain any word file. On adding any file/files to the folder I need to parse the file and based on some keywords I need to transfer the file to some other sub folders as well as some entry to the database also.
I know something about FileSystemWatcher. If there would have been a button like "Check and Move" then I know that on the button click event I can do something but how to do it automatically. I mean if I add file to the folder manually also it should do the same(files may be uploaded via web as well as manually).I am currently working in web application with asp.net and c# and I have a little knowledge about windows application. Can any one suggest me how to proceed with this? Thanks.
You will need to create either a windows app or a windows service app. The FileSystemWatch won't survive on a web application. The reason is because web application functions by following the steps:
the webserver thread loads the application
your application starts the watcher and then finally output the web response.
After some idle time, the thread terminates the application, and thus your watcher.
When you have your windows app, you can add the CanRaiseEvents = true and w.Created += new System.IO.FileSystemEventHandler(w_Created); to your watcher. Do your processing in
void w_Created(object sender, System.IO.FileSystemEventArgs e)
{
// here
}
I just happened to be researching something very similar.
But you answered your own question. FileSystemWatcher is likely what you want.
Lower level Win32 APIs information is here:
Obtaining Directory Change Notifications
and here:
FindFirstChangeNotification
currently I’m creating 2 applications (app A and B) for Windows Mobile 5.0 and using Compact Framework 2.0. App A is the main application and B is the sub application.
Below is the flow:
Start app A.
App A will start app B.
App B will do some process.
App B will kill app A.
App B will patch/upgrade app A. (ala update manager)
App B will restart app A.
App B will exit.
Now I’m stuck in killing app A. I did tried using OpenNETCF ProcessEntry Kill() function. When calling Kill(), it made the device crash.
I did tried using the SendMessage(hWnd, WM_CLOSE, 0, 0) funct where WM_CLOSE will have the ProcessEntry.ProcessID value and I didn’t assigned any value to hWnd variable. But it didn’t terminate app A. Did I assign the wrong value?
I also did tried using
Process.GetProcessById(processEntry.ProcessID).CloseMainWindow()
, but failed as GetProcessById only accepts int32 value. Note that processEntry.ProcessID value is larger than int32 value and GetProcessByName() is not supported in Compact Framework.
Could you help me in killing app A through app B?
Thanks.
You may try native code, using the TerminateProcess function:
processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid);
success = TerminateProcess(processHandle, 0);
The above code is from a Task Manager at Code Project.
However if you are writing the code for both the applications, it will be better if you designed a communication mechanism between the two applications. In this way you will send a message from app B to app A and app A will kill itself.
Stormenet, I hardcoded the application's name. Then I generate an object to get all the available process using OpenNETCF.ToolHelp.ProcessEntry[ ] = ProcessEntry.GetProcesses();
then in a foreach loop, if the ProcessEntry object eg: processEntry.ExeFile matches with the "applicationName", i shall use processEntry.Kill().
I think you can get the OpenNETCF.ToolHelp dll from the OpenNETCF site.
Note that if the application you are trying to kill is holding open ports or other system resources then it might hang on exiting. Ensure everything is effectively disposed when the form closes.
This can be acheived by putting stuff in the:
public void Dispose(bool disposing)
{
}
block of code in the designer of your main form, or if you've chosen a less Windows Form centric architecture then just run your dispose calls following Application.Run(new YourForm()) and it will execute after the application has closed.
If you're feeling really lazy then just setup some destructors (otherwise known as finalizers ~) but be careful about navigating through relationships between managed objects at "destruct" time if you do this as there is no guarantee as to which order objects will be destroyed.
ctacke, I think app A crashes due to some of the running threads are not closed properly or still running at the background as app A will run multiple threads during app B executing the Kill( ) function.
If I use the SendMessage(hWnd, WM_CLOSE, 0, 0) function, it will not crash the device (which is a good thing)... it only closes the form. (app A contains multiple forms eg: frmLogin and frmMainMenu). hmmm maybe I need to point hWnd to the right form...
Now I'm taking a different route.
After downloading the patch and put it in a temp folder, I'll do a soft reset using OpenNETCF.WindowsCE.PowerManagement.SoftReset().
App B will be launched upon startup, then it will scan the temp folder and replace app A with the new version.