简体   繁体   中英

how do i send a custom message to a windows service?

I have implemented a windows xp service application that starts a couple of working threads. From one of the threads i need to send custom messages back to the service. How do i do that?

一种选择是使用OmniThreadLibrary (有关示例,请阅读此博客文章 )。

Thanks for your help. Here is how I solved the problem:

In the Service class definition:

  WHandle: HWND;
protected
  procedure HandleServiceMessage(var Msg: TMessage); virtual;

In the ServiceExecute method:

  WHandle := AllocateHWnd(HandleServiceMessage);
  MyThread := TMyThread.Create(true);
  MyThread.HndMain := WHandle;
  MyThread.Resume;
  while not Terminated do ServiceThread.ProcessRequests(True);
  DeallocateHWnd(WHandle);
end;

In ServiceStop method:

  MyThread.Terminate;

And the method for handling messages:

procedure TMessageService.HandleServiceMessage(var Msg : TMessage);
var
  Handled: Boolean;
begin
  Handled := True;
  if Msg.Msg = WM_MYMESSAGE then
    Beep
  else
    Handled := False;
  if Handled then
    Msg.Result := 0
  else
    Msg.Result := DefWindowProc(WHandle, Msg.Msg, Msg.WParam, Msg.LParam);
end;

In MyThread.Execute method:

  PostMessage(HndMain,WM_MYMESSAGE,0,0);

Its working just fine.

I agree with TOndrej that shared objects should be sufficient.

On the other hand you can use my IPC ( Cromis IPC ) which works just fine inside services. It is easy to use, message oriented, so you don't need to know how named pipes work and very fast. The server part also uses a thread pool, so there is no waiting for something to be processed. You can use the fire and forget scenario.

Or if you think a little redesign is ok, you can try OmniThreadLibrary which has all the messaging already build in and is made for tasks like this.

EDIT :

Ok probably the cleanest way to go, without any redesing is to have a common object list which is protected by a critical section. The working thread is adding objects that need to be processed in the list. When and object is added the working thread signals an event. Then you have an object processing thread which is waiting with WaitForSingleObject for this event. As soon as something is added to the list the event is signaled and the processing thread just processes all the objects it finds in the list. Then it waits again. All you need to do is to protect the access to the common list.

Simplified the code would look like this:

WORKER THREAD

ObjectList.Add(MessageObject);
SetEvent(FEvent);

PROCESSING THREAD

while not Terminated do
begin
  WaitForSingleObjest(FEvent, INFINITE);
  // process all the objects
end;

Creating message-only window:

procedure TMyService.MessageQueueDispatch(var Message: TMessage);
begin
  Dispatch(Message); //Delphi default dispatcher for TMyService
end;

procedure TMyService.SomeKindOfOnCreate;
begin
  MessageQueue := AllocateHWnd(MessageQueueDispatch);
end;

Destroying:

procedure TMyService.SomeKindOfDestroy;
begin
  CloseHandle(MessageQueue);
end;

Now you can handle messages like you would do with form messages:

TMyService = class(TService)
...
protected
  procedure HandleMyMessage(var msg: TMsg); message WM_MY_MESSAGE;
end;

Delphi Dispatch() handler will take care of calling the function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM