views:

663

answers:

7

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 know only C#)

EDIT: Purpose: Basically I have to debug a windows service for fixing a bug that occurs only on system shut down.

+1  A: 

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.

Brian R. Bondy
but I have to send message to a process running as a windows service? How does FindWindow work in this case?
iJeeves
The service would have to have a window in the first place or message queue to be able to send it messages. And depending on Vista settings you may not be able to send the message anyway to a service which runs in a different session. If you have control of the service a better option would be pipes.
Brian R. Bondy
+2  A: 

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.

shoosh
+1  A: 

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.

ThePower
How can I find out the handle of the Windows Service. Sorry, I'm new to win32.
iJeeves
See the edit! :-)
ThePower
Thank you! Will try out and update here.
iJeeves
+2  A: 

Services should be controlled using ServiceController class

You can use it to start, stop and communicate with services.

Diaa Sami
+3  A: 

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.

Rowland Shaw
i have a feeling that dependencies don't help on shutdown... but i'm not sure on that.
Rory
A: 

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;
CM
+1  A: 

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().

Rory