2012-03-30 17 views
5

小さなウィンドウサービスを仲介して、起動中に別のプロセスからの信号を待つようにしています。そのようなアプローチがサービス起動のタイムアウトにつながることがあることは確かです。そうではありません。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); 
    } 
} 

ので、上のヘルプはlookigこの。

PS:私はMutexを代わりに使用しようとしていましたが、別の問題がありました。所有者がMutex.ReleaseMutex()を呼び出すと、待機中のアプリケーションが追いついていません。

UPDATE

次のように私は、セマフォ作成ルーチンを編集したとブツは今、正常に動作アヌラーグRanjhan応答を1として:

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

答えて

5

Global\接頭

System.Threading.Semaphore rootSemaphore = 
new System.Threading.Semaphore(1, 1, "Global\DummyServiceSemaphore", out newOne); 
で使用してみてください

よりcomment section of MSDN

Windowsで名前付きセマフォを使用している場合、選択する名前はカーネル命名ガイドラインの適用を受ける です。これらのガイドラインの一部には、カーネルオブジェクトのコンテキスト を記述するカーネルオブジェクトネームスペース1も含まれています( )。既定では、ターミナルサービスをインストールすると、イベントのような カーネルオブジェクトは現在のセッションに制限されます。これは であるため、ターミナルサービスで実行されている複数のセッションで悪影響を受けることはありません カーネルオブジェクト名前空間は、 が特定の名前空間に適用され、特定のスコープのプロセスと通信するか、または通信するように、 "ローカル\"、 "グローバル\"と "セッション"接頭辞を使用して記述します。

+0

ありがとうございました!それが問題を解決しました。 – Vitaly

+1

私は最近、同じ問題を抱えていましたが、 "グローバル\"接頭辞を使用しても、Windowsサービス内で動作するように、上記の質問の更新に示されているようにSemaphoreSecurityオブジェクトを明示的に指定する必要がありました。それは、しかし、仕事をした! – mthierba

関連する問題