views:

651

answers:

3

Hi there, I have created a windows service that uses Windows Messaging System. When I test the app from the debugger the Messages go through nicely but when I install it my messag … asked 14 mins ago

vladimir 1tuga

+5  A: 

What do you mean when you say it "uses" Windows Messaging System? Are you consuming or sending Windows Messages?

If you send a Windows message, you need ensure you are doing it correctly. I'd suggest writing a message loop to ensure your messages are being dispatched properly. I'd also suggest reading up on message loops and how they work.

What is a Message Loop (click the title to be taken to the source of this info)

while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
    TranslateMessage(&Msg);
    DispatchMessage(&Msg);
}
  1. The message loop calls GetMessage(), which looks in your message queue. If the message queue is empty your program basically stops and waits for one (it Blocks).
  2. When an event occures causing a message to be added to the queue (for example the system registers a mouse click) GetMessages() returns a positive value indicating there is a message to be processed, and that it has filled in the members of the MSG structure we passed it. It returns 0 if it hits WM_QUIT, and a negative value if an error occured.
  3. We take the message (in the Msg variable) and pass it to TranslateMessage(), this does a bit of additional processing, translating virtual key messages into character messages. This step is actually optional, but certain things won't work if it's not there.
  4. Once that's done we pass the message to DispatchMessage(). What DispatchMessage() does is take the message, checks which window it is for and then looks up the Window Procedure for the window. It then calls that procedure, sending as parameters the handle of the window, the message, and wParam and lParam.
  5. In your window procedure you check the message and it's parameters, and do whatever you want with them! If you aren't handling the specific message, you almost always call DefWindowProc() which will perform the default actions for you (which often means it does nothing).
  6. Once you have finished processing the message, your windows procedure returns, DispatchMessage() returns, and we go back to the beginning of the loop.
Mick
While this is great general information on message processing in Windows, it doesn't apply directly to Delphi where the message loop and even the actual message object are typically hidden from the developer.
Scott W
What do you mean "hidden"? I can translate this exact code to Delphi (and I've done this in production projects), and WHAM, I have a message loop. They are simply apart of the API, which Delphi can fully access and use just like in C/C++
Mick
True, you can do this, but I meant that you don't have to. For example, I can create a new project with a form and set up a handler for a particular message type. Then, without any attempt at building a message processing loop, my handler will receive those messages.
Scott W
You are correct. If you create a VCL application, this is not necessary. However, if you create a console application and you want to send Window Messages from it, then you would need a message loop.
Mick
Ah, OK. I have not done console programming via Delphi.
Scott W
+4  A: 

Services don't generally receive window messages. They don't necessarily have window handles at all. Even if they do, they run in a separate desktop. Programs cannot send messages from one desktop to another, so a service can only receive messages from another service, or from a program started by a service.

Before Windows Vista, you could have configured your service to interact with the desktop. That makes the service run on the same desktop as a logged-in user, so a program running as that user could send messages to your service's windows. Windows Vista isolates services, though; they can't interact with any user's desktop anymore.

There are many other ways to communicate with services. They include named pipes, mailslots, memory-mapped files, semaphores, events, and sockets.

With a socket, for instance, your service could listen on an open port, and programs that need to communicate with it could connect to that port. This could open the door to remote administration, but you can also restrict the service to listen only for local connections.

All the above is trying to tell you that you're taking the wrong approach. But there's also the matter of the problem at hand. Your program behaves one way in the debugger and another way outside it. How are you debugging the service in the first place, if it's not installed? What user account is your service running as? Your debugger? What debugging techniques have you tried that don't involve the debugger (e.g. writeln to a log file to track your program's actions)?

Rob Kennedy
Services in Delphi DO have the ability receive window messages without creating a message pump. To prove this, create a service in Delphi, and you will notice something that creates a form (e.g. a 'hidden' window like a normal VCL app): Application.CreateForm(TMyService1, MyService1);
Mick
Nonetheless, it can't receive messages from a program running in another desktop.
Rob Kennedy
Yes, that is true in Windows Vista. That is because the service is running with SYSTEM privileges, and its process has a higher IL (Integrity Level) than an application run by the user. Its possible to elevate the IL of an app and send WM's to a service. But this isn't feasible with a production app
Mick
A: 

Thank you all for the answers, the issue was the operating system (vista), i tested the with my windows 2000 and everything works.

thanks for the light Rob.