1

我目前正在使用 c# 和 .net framework 4.5 开发一个 Windows 服务,以扩展现有专有应用程序的功能,该服务阻塞在 EventWaitHandleClass ( msdn link ) 上,等待从主应用程序发出的命名事件。像这样的东西:

bool boolWithFalse = false;
string eName = "notification_event";
string usr = Environment.UserDomainName + "\\" + Environment.UserName;
EventWaitHandleSecurity security = new EventWaitHandleSecurity(); //*
EventWaitHandleAccessRule rule = new EventWaitHandleAccessRule(usr, EventWaitHandleRights.Synchronize, AccessControlType.Allow);
security.AddAccessRule(rule);
EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.ManualReset, eName, out boolWithFalse, security);

//... some non relevant code lines here

//This is where the it locks waiting for the named event
var w = EventWaitHandle.WaitAny(new[] { handle }, Timeout.Infinite);

*:事件等待句柄安全 MSDN

现在,如果我将程序作为控制台应用程序执行,这就像一个魅力,我可以轻松地从主应用程序捕获事件并按照我的意图处理它们,但是,当我将应用程序安装为服务时,它会锁定等待这个相同的命名事件但永远不会收到信号。该服务设置为使用 NT AUTHORITY\LOCALSERVICE 帐户运行,我已经尝试使用我自己的帐户(程序在作为控制台应用程序运行时使用),但没有任何反应。

如果它有助于发起信号的应用程序在我自己的帐户下运行。感谢任何帮助,因为我是为 Windows 开发桌面应用程序的完整初学者。

4

1 回答 1

2

你在安全的喧嚣中迷路了。两个问题。第一个是必须有人创建事件而其他人必须打开它,因此两个组件共享同一个事件对象。其中一个必须使用 EventWaitHandle 构造函数,另一个必须调用 EventWaitHandle.OpenExisting() 方法。正常的方式是服务创建事件并由 UI 程序打开它。

下一个问题是事件对象的可见性。Windows 为命名的操作系统对象实现命名空间,这与您在 C# 语言中使用命名空间的方式非常相似。根命名空间由会话命名。并且服务在与用户的桌面程序不同的会话中运行。要让桌面会话程序看到在服务会话中创建的事件,您必须使用“全局”事件名称。看起来像这样:

 string eName = "Global\\notification_event";

请注意如何命名全局可见的命名事件。某天某个地方的另一个程序员认为“notification_event”是一个不错的名称选择。你不想见他。{guid} 是个好名字,你可以从 Tools + Create GUID 中得到一个。它在已知宇宙中是独一无二的,可能更远。

于 2014-01-09T23:50:40.380 回答