Is there any tool to send (mimic) a windows message like \'WM_ENDSESSION\' to a windows service?
OR
How can I send a windows message to a process using C#?
I would recommend Importing and defining the following:
[System.Runtime.InteropServices.DllImportAttribute("user32.dll")]
public static extern bool PostMessage(IntPtr handleWnd, UInt32 Msg, Int32 wParam, Int32 lParam);
const int WM_ENDSESSION = 0x0016,
WM_TRUE = 0x1,
WM_FALSE = 0x0;
Then send through 0x1 or 0x0 representing true or false as the wParam message.
So in your code you will use:
PostMessage(HandleToSendTo, WM_ENDSESSION, WM_TRUE, 0);
Where HandleToSendTo is the Window Handle of the window you would like to send the message to.
Edit
To get the windows handle if you don't know it, I'm assuming that you will know it's title or name. If so you can use this:
[DllImport("user32.dll", EntryPoint = "FindWindowEx")]
public static extern int FindWindowEx(int hwndParent, int hwndEnfant, int lpClasse, string lpTitre);
Which more information about can be found in this question.
Or maybe
I don't know if this is a similar handle, I doubt it, but someone could let me know if it is, but you can get a Process handle, which means you could get the process using Process.GetProcessesByName("MyAppName");, althought don't rely on this as I don't think that it will get the handle that you are after. Just a suggestion.
If you have the hwnd of a window you can send it messages. The only limitation is that you can't send messages that contain pointers like setting window text.
Simply call PostMessage()
with the value of the hwnd and the message you want to send.
To find the hwnd you can use spy++.
I'm not sure how you connect all this to windows services since windows services don't have windows.
I don't think there is a tool to send arbitrary messages because each message can have arbitrary LPARAM and WPARAM values.
But the most useful tool surrounding windows messages is spy++. Spy++ is included with Visual Studio and it helps you see what messages are sent, window hierarchy, and more.
You can send messages via C# with the SendMessage Win32 API. You can get the window handle it asks for by using a Win32 API like FindWindow or FindWindowEx.
Edit (to match question's edit): Services are stopped by windows automatically on shutdown. So to fix your bug it sounds like you need to modify the code of the service itself to properly shut down.
Edit2: Or if you want to stop the service you should use the Win32 API ControlService passing in SERVICE_CONTROL_STOP
0x00000001
.
Check out the answers to How to simulate windows shutdown while debugging?
Services have an 'event' called OnShutdown they can subscribe to, so it could be the problem is in that code. If the code is .net you could subclass it so you can call the protected OnShutdown method to debug. But the problem could also be as suggested by others that the service is expecting resources to be available which aren't because they've already been closed.
Also, if the service was written in .net 2.0 note that the Stop() command isn't called automatically on a service when the workstation is being shut down! This is very surprising and was fixed in .net 3.5, but if you're using .net 2.0 you need to call Stop() yourself within OnShutdown().
I don't know if this is a similar handle, I doubt it, but someone could let me know if it is, but you can get a Process handle, which means you could get the process using Process.GetProcessesByName("MyAppName");, althought don't rely on this as I don't think that it will get the handle that you are after. Just a suggestion.
Actually this method will work...you just need to access the 'MainWindowHandle' property of the process object. For Instance...
Process myProcess;
Int handle;
myProcess = Process.GetProcessesByName("MyAppName");
handle = myProcess.MainWindowHandle;
Generally, services don't have windows (let alone message pumps) to receive a windows message.
If the bug really does only happen on shutdown (as opposed to just stopping the service), it may be the case that something depends on a resource that is going away, which is not being handled gracefully (in which case, the bug fix might be to set up the service dependencies correctly). Have you tried using the remote debugging tools to attach to the process prior to shutdown?
It's worth investigating if you can get the problem to occur without shutting down, perhaps when just stopping the service with the Service Control Manager (no need to do this programmatically, as this is a debugging scenario), in which case, you can breakpoint OnStop() in your service (I'm assuming C#) and watch what happens.