好吧,长话短说,我有一个 Windows 服务可以处理 Win32_VolumeChangeEvent 并将 USB 磁盘设备到达记录到事件日志和 SQL 数据库中。另一个组件是一个隐藏的 UI (WinForms),它在登录时加载到用户 session 中——这会弹出一个消息框,提醒用户有关 USB key 等的公司政策。据我所知,这是最好的方法,因为服务无法在交互模式下运行时间更长。
任何人......在架构上,这个小东西的 v1 与处理设备插入的 WndProc 消息的 UI 组件一起运行,然后通过 IPC(命名管道)将设备标识符传递给将处理 WMI 方法/事件日志写入的服务(如并非所有用户都具有本地管理员权限)。这样做的缺点是 UI 元素被进程杀死并且不再检测设备插入。
因此,当前版本是服务处理 Win32_VolumeChangeEvents 并从设备获取所需的详细信息,然后记录到 EventLog 和 SQL。一切都很出色,工作完美。除了现在我想知道触发 UI 显示弹出窗口的最佳方法是什么。
我已经在 Google 和此处进行了研究,寻找有关通过 IPC 进行事件处理的想法,因此我可以从 UI 组件订阅一个事件并在服务中触发它,但我没有发现太多像乐于助人。我也受限于 .net2,所以 WCF 不在考虑之列(尽管如果您想那样做,我不害怕 p/invoke)。
所以。你会怎么做?链接、想法、漫谈、伪代码、实际代码……所有这些都值得赞赏。我努力坚持我认为的最佳实践,尽管我也认为编程是一种艺术形式,我的最佳实践可能是别人的恐怖故事。
所以 SO - 你会怎么做?让我知道是否需要澄清:)
最佳答案
回到过去糟糕的 Windows API 编程时代,我们有时会使用 RegisterWindowMessage
来注册一个(大概)只有我们的窗口知道如何处理的唯一消息 ID。然后,我们可以通过使用 HWND_BROADCAST
的窗口句柄调用 PostMessage
来从另一个应用程序触发该窗口,并且 msg
参数是该唯一消息值。如果您希望在进程之间共享的所有内容都可以放入两个 DWORD
值(wparam
和 lparam
),那效果会很好。如果分配全局内存并将引用作为参数之一传递,则可以共享更多数据。
使用 .NET 应该仍然可以做到这一点。当然调用PostMessage
是没有问题的。至于在 UI 代码中处理消息,您必须覆盖 Form 的 WndProc
。参见 How do I send/receive windows messages between VB6 and c#?举个例子。
您可以对命名事件做一些事情,尽管这只会通知 UI 发生了一些变化。它实际上不会告诉你发生了什么。我想,如果只有一小部分可能的事件,您可能会有多个事件,但这很快就会变得复杂。
您可以使用命名的事件路由并使用共享内存(内存映射文件)来共享状态。
或者,您可以设置套接字、命名管道、TcpListener
/TcpClient
,甚至是 UdpClient
。一切都应该有效,但具有不同程度的复杂性和/或可靠性。
关于跨 IPC 的 C# 事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4939217/