在服务中接收Windows消息

4
我已经用VC++编写了一个服务。我按照这里的教程进行操作。现在,我正在尝试找出如何接收消息,例如DBT_DEVICEARRIVAL、DBT_DEVICEREMOVECOMPLETE、WM_COPYDATA等,就像普通应用程序具有顶级窗口一样。当我搜索时,我发现了这篇MSDN文章
在“广播消息”部分的最后一段中:
应用程序通过其顶级窗口的窗口过程接收消息。消息不会发送到子窗口。服务可以通过窗口过程或其服务控制处理程序接收消息。
但几乎不可能找到任何如何执行此操作的示例。
  1. 如何将WndProc与我的服务关联,以便接收消息?

  2. 或者,如何使我的服务控制处理程序函数接收Windows消息?我的服务控制处理程序只有一个DWORD参数,没有WndProc的UINT、WPARAM、LPARAM等。

我已经阅读了一些关于使用隐藏窗口和仅消息窗口等方法的内容,但我不认为我可以在服务中使用它们;也不想使用。如果我能够用MSDN提到的这两种方法中的任一种实现它,那就太好了。

服务描述:

该服务将检测USB设备插入并复制一些文件到其中。它还必须跟踪某些目录和文件的更改,以便知道要复制哪些文件。

这个基本功能可以扩展到包括其他事情,在未来可能需要接收许多其他我现在不知道的Windows消息。

上面提到的示例消息只是从我开发常规Windows应用程序时习惯于使用的内容中摘取的。我理解如果在编写服务时它们不适合或不安全。


1
由于0会话隔离,您将无法收到许多消息。 - David Heffernan
2个回答

3

您只需创建一个普通的消息循环,就像编写纯C实现的Win32窗口应用程序一样 - 不涉及任何框架。

例如:

while(GetMessage(...)) ...

你可以使用PeekMessageGetMessage(参见链接文档)。但后者更加常规且可以将其从消息队列中删除。
也就是说,你甚至不需要一个窗口。每个线程都可以有一个消息循环。因此它将被阻塞,但仅限于当前线程。你需要自己想出如何将信息传递到需要它的其他线程。
然而,与其在妥协上花时间,你应该阅读Wikipedia上的Shatter攻击并为服务使用适当的IPC技术(有许多可用的选项,从MMF到管道再到与信号量、互斥量和事件的组合)。
如果你打算在用户桌面上接收窗口消息,但使用特权上下文进行操作,则这部分内容是相关的(尽管会话分离本来就应该防止这种情况发生)。

尝试过了。while循环阻止了方法的返回,因此我的服务甚至无法启动。有什么想法在哪里/如何放置它,以便服务实际上开始运行? - user1699872
@显示名称:每个线程都可以有自己的消息循环。谁强制你将其放在“主”(即第一个)线程中? - 0xC0000022L
那么,也许我应该把它放在服务工作线程中? - user1699872
@显示名称:这取决于您的意思。如果您指的是服务的“Handler”/“HandlerEx”,那么问题仍然存在-您只是将其推迟到SCM接管之后失败。 - 0xC0000022L
嗯..我会尝试弄清楚如何使用线程来处理消息循环并与其他线程通信。还有,谢谢提供的链接。我会查看其他的进程间通信技术。 - user1699872

2

好的替代方法!+1 - 0xC0000022L
HandlerEx 对我来说是一个可行的选择。但它的控制代码列表似乎只涵盖了有限的一组事件。想知道这些代码(即使是扩展列表)是否涵盖了服务可能需要的 EVERYTHING? - user1699872
@显示名称:对于设备通知来说,这已经足够了。但是,一旦你开始变得愚蠢(你读了我的答案吗,特别是粗体标题后面的部分吗?),你不仅自己一个人,而且还在积极地违反系统的工作方式。 - 0xC0000022L
我正在使用Shell服务进行此操作,但这是另一段故事。 :) - Xearinox
2
@显示名称:请告诉我们为什么您需要在服务中使用类似于您问题中提到的WM_COPYDATA的东西? - 0xC0000022L

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接