Служба Windows не видит именованный семафор - PullRequest
6 голосов
/ 30 марта 2012

Я пытаюсь стать посредником небольшой службы 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);
    }
}

Итак, ищите помощь по этому вопросу.

PS: я пытался использовать Mutex вместо этого, однако была другая проблема с ним - ожидающее приложение не догоняет, когда владелец вызывает Mutex.ReleaseMutex ();

UPDATE

Согласно ответу Анурага Ранджана, я отредактировал подпрограмму создания семафора следующим образом, и штука теперь работает нормально:

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);

1 Ответ

6 голосов
/ 30 марта 2012

Попробуйте использовать с Global \ префиксом

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

В разделе комментариев MSDN

Если вы используетеименованный семафор в Windows, выбранное вами имя регулируется правилами именования ядра.Некоторые из этих рекомендаций также включают пространства имен объектов ядра 1 , которые описывают контекст объекта ядра.По умолчанию с установленными службами терминалов объекты ядра, такие как события, ограничены текущим сеансом.Это сделано для того, чтобы несколько сеансов, запущенных в службах терминалов, не оказывали отрицательного влияния друг на друга.Пространства имен объектов ядра описывают использование префиксов «Local \», «Global \» и «Session \» для создания объектов ядра, которые могут применяться к конкретным пространствам имен, а также для связи или ограничения связи с процессами определенной области.

...