在Windows Service中创建时无法找到命名事件
本文关键字:事件 Service Windows 创建 | 更新日期: 2023-09-27 18:07:45
我正在用c#开发一个Windows Service来集中管理一些应用程序连接。它通常是一个休眠服务,在被外部可执行文件唤醒时执行一些操作。为此,我使用了命名事件,特别是. net EventWaitHandle
。在服务端,我的代码可以归结为:
EventWaitHandleSecurity sec = new EventWaitHandleSecurity();
sec.AddAccessRule(new EventWaitHandleAccessRule(
new SecurityIdentifier(WellKnownSidType.WorldSid, null),
EventWaitHandleRights.FullControl,
AccessControlType.Allow));
evh = new EventWaitHandle(false, EventResetMode.AutoReset, EVENT_NAME,
out created, sec);
Log(created ? "Event created" : "Event already existed?");
作为一个内部应用程序在可信的服务器上,我不介意授予'完全控制' '世界'一般不会是明智的。
客户端:
EventWaitHandle.TryOpenExisting(EVENT_NAME, EventWaitHandleRights.Modify, out evh)
当我在基于控制台的交互模式下运行我的服务时,上面的代码可以完美地工作。在两端都找到事件,客户端可以设置,服务开始工作。每个人的快乐。
安装服务时,它不工作。日志记录仍然报告事件已重新创建,但客户端无法找到该事件。因为我认为这与安全有关,所以我添加了世界完全控制允许访问规则,但它没有改变任何东西。我将服务更改为以本地管理员身份运行,甚至以我自己的用户帐户运行,但是什么也没有-客户机无法找到事件,即使日志显示服务正在愉快地轮询它。如果我将TryOpenExisting
更改为OpenExisting
,我会得到一个显式异常:
System.Threading.WaitHandleCannotBeOpenedException: No handle of the given name exists.
我错过了什么?
从Windows Vista开始,服务被隔离并在会话0中运行(参见Windows Vista的服务更改)。当调用CreateEvent (EventWaitHandle执行)时,默认情况下在本地命名空间(也称为会话命名空间)中创建事件对象。服务在会话0中创建的事件对象,其名称在会话命名空间中,仅在会话0中可见。对于在交互式用户会话中运行的应用程序是不可见的。
要通过服务(运行在会话0中)创建一个可以被应用程序代码(运行在交互式用户会话中)发现的事件对象,您必须将其创建到全局命名空间中。这是通过在事件名称前加上"Global'"来完成的,如CreateEvent中所述。
一个有用的工具来跟踪内核对象相关的错误是Sysinternal的WinObj。