【问题标题】:Windows service cannot see named semaphoreWindows 服务看不到命名信号量
【发布时间】:2012-03-30 15:24:56
【问题描述】:

我正在尝试调解一个小型 Windows 服务,使其在启动期间等待来自另一个进程的信号。我当然知道这种方法有时可能(甚至会)导致服务启动超时。事实并非如此。

问题在于我用于调解目的的命名 System.Thread.Sempaphore。信号量是使用以下构造在其他地方创建和获取的。 GC 没有任何变化,因为我出于测试目的明确地在给定行下方中断了执行。

Boolean newOne;
System.Threading.Semaphore rootSemaphore = 
    new System.Threading.Semaphore(1, 1, "DummyServiceSemaphore", out newOne);

显然,上面的代码运行良好。以下代码在调试模式下或控制台应用程序下运行良好:

Boolean createdNew;
System.Threading.Semaphore semaphore = 
    new System.Threading.Semaphore(1, 1, "DummyServiceSemaphore", out createdNew);
if (createdNew) 
    throw new Exception("That's not what we wanted");

完全相同的代码在作为 Windows 服务的一部分执行时会失败:

static class Program
{
    static void Main(string[] args)
    {
        Boolean createdNew;
        System.Threading.Semaphore semaphore = 
            new System.Threading.Semaphore(1, 1, "DummyServiceSemaphore", out createdNew);
        if (createdNew) 
            throw new Exception("That's not what we wanted");

        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] { new Dummy() };
        ServiceBase.Run(ServicesToRun);
    }
}

为什么会失败?

我一直在尝试改用 Mutex,但是它还有另一个问题 - 当所有者调用 Mutex.ReleaseMutex(); 时,等待的应用程序没有赶上;


更新

根据 Anurag Ranjhan 的回复,我编辑了信号量创建例程,如下所示,现在一切正常:

Boolean newOne = false;

System.Security.Principal.SecurityIdentifier sid = 
    new System.Security.Principal.SecurityIdentifier(
        System.Security.Principal.WellKnownSidType.WorldSid, 
        null);

System.Security.AccessControl.SemaphoreSecurity sec = 
    new System.Security.AccessControl.SemaphoreSecurity();
sec.AddAccessRule(new System.Security.AccessControl.SemaphoreAccessRule(
    sid,
    System.Security.AccessControl.SemaphoreRights.FullControl,
    System.Security.AccessControl.AccessControlType.Allow));

System.Threading.Semaphore rootSemaphore = 
    new Semaphore(1, 1, "Global\\DummyServiceSemaphore", out newOne, sec);

【问题讨论】:

    标签: c# windows-services semaphore


    【解决方案1】:

    尝试使用 Global\ 前缀

    System.Threading.Semaphore rootSemaphore = 
    new System.Threading.Semaphore(1, 1, @"Global\DummyServiceSemaphore", out newOne);
    

    来自comment section of MSDN

    如果您在 Windows 中使用命名信号量,您选择的名称是 受内核命名准则的约束。其中一些准则还 包括 Kernel Object Namespaces1,它描述了上下文 内核对象。默认情况下,安装了终端服务, 像事件这样的内核对象仅限于当前会话。这是 这样做,在终端服务中运行的多个会话不会产生不利影响 互相影响。内核对象命名空间使用“本地”描述, “全局”和“会话”前缀来创建内核对象,可以 适用于特定的命名空间并与之通信或限制 与特定范围的进程通信。

    【讨论】:

    • 我最近遇到了同样的问题,即使使用“Global\”前缀,我仍然必须明确指定 SemaphoreSecurity 对象,如上面的问题更新中所示,以使其在内部工作视窗服务。然而,它完成了工作!
    • 只是小修复,必须转义\或@前缀:"Global\\DummyServiceSemaphore"@"Global\DummyServiceSemaphore"
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-22
    • 1970-01-01
    • 2012-08-01
    • 2012-10-08
    • 2011-10-23
    • 2013-02-13
    相关资源
    最近更新 更多