2012-03-30 5 views
5

Ich versuche, einen kleinen Windows-Dienst vermitteln, so dass es auf ein Signal von einem anderen Prozess während des Starts warten. Sicherlich weiß ich, dass ein solcher Ansatz manchmal zu einem Timeout beim Dienststart führt (oder sogar wird). Das ist nicht der Fall.Windows-Dienst kann nicht sehen, Semaphor

Das Problem ist mit dem Namen System.Thread.Sempaphore ich für Vermittlungszwecke verwenden. Semaphore wird erstellt und erworben woanders mit folgendem Konstrukt. Es gibt keine Änderung GC hat es, da ich die Ausführung direkt unterhalb der angegebenen Zeile für Testzwecke explizit breche.

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

Code oben funktioniert natürlich gut. Folgender Code funktioniert gut, wenn im Debug-Modus oder unter Konsolenanwendung ausgeführt wird:

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

Genau der gleiche Code schlägt fehl, wenn als Teil des Windows-Dienstes ausgeführt wird:

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

Also, um Hilfe lookig auf Dies.

PS: Ich habe versucht, stattdessen Mutex zu verwenden, aber es gab ein anderes Problem damit - wartende Anwendung holt nicht auf, wenn Besitzer Mutex.ReleaseMutex() aufruft;

UPDATE:

Wie pro Anurag Ranjhan Antwort habe ich bearbeitet Semaphore Routine wie folgt zu erstellen und das Ding funktioniert jetzt:

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

Antwort

5

Versuchen mit Global\ Präfix

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

Von der comment section of MSDN

Wenn Sie einen benannten Semaphor in Windows verwenden, lautet der von Ihnen gewählte Name , der sich an den Regeln für die Kernel-Benennung orientiert. Einige dieser Richtlinien enthalten auch die Kernel-Objekt-Namespaces 1, die den Kontext des Kernel-Objekts beschreibt. Wenn die Terminaldienste installiert sind, sind Kernel-Objekte wie Ereignisse standardmäßig auf die aktuelle Sitzung beschränkt. Dies ist getan, so dass mehrere Sitzungen im Terminal-Dienste laufen nicht nachteilig beeinflussen sich gegenseitig. Kernel-Objekt-Namespaces beschreiben mit "Local \", Präfix "Global" und "Session", um Kernel-Objekte zu erstellen, die auf bestimmte Namespaces angewendet werden können und mit Kommunikation zu Prozessen eines bestimmten Bereichs kommunizieren können.

+0

Vielen Dank! Das hat das Problem gelöst. – Vitaly

+1

Ich hatte dieses Problem in letzter Zeit, und selbst mit dem Präfix "Global" musste ich das SemaphoreSecurity-Objekt noch explizit angeben, wie in der obigen Frage angegeben, damit es in einem Windows-Dienst funktioniert. Das hat aber seinen Zweck erfüllt! – mthierba