简体   繁体   English

如何向Windows服务发送自定义消息?

[英]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. 我已经实现了一个Windows XP服务应用程序,该应用程序启动了几个工作线程。 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: 在ServiceExecute方法中:

  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: 在ServiceStop方法中:

  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: 在MyThread.Execute方法中:

  PostMessage(HndMain,WM_MYMESSAGE,0,0);

Its working just fine. 它工作得很好。

I agree with TOndrej that shared objects should be sufficient. 我同意TOndrej的观点,共享对象应该足够了。

On the other hand you can use my IPC ( Cromis IPC ) which works just fine inside services. 另一方面,您可以使用我的IPC( Cromis IPC ),它在服务内部运行良好。 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. 或者,如果您认为可以进行一些重新设计,则可以尝试使用OmniThreadLibrary,它已内置了所有消息传递,并且可用于此类任务。

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. 然后,您有一个对象处理线程正在与WaitForSingleObject等待此事件。 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. Delphi Dispatch()处理程序将负责调用该函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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