2016-04-13 22 views
5

アプリケーションのテスト中に、私は奇妙な動作に陥りました。テストの中には、偽装を使用してコードを別のユーザーとして実行するものもありますが、それらは常にハングアップして完了することはありません。偽装を使用している間にミューテックスの作成がハングアップする

いくつかの調査の後、問題はミューテックスの使用に絞られました。もともとは、MSDN documentationに基づく独自の偽装コードを使用しましたが、SimpleImpersonation libraryを使用しても問題は残ります。ここ は、問題を再現するために、最小限の例です。

using (Impersonation.LogonUser(DOMAIN, USER, PASSWORD, LogonType.Interactive)) 
{ 
    Console.WriteLine("Impersonated"); 
    bool mine; 
    using (new Mutex(true, "Mutex", out mine)) 
    { 
     if (!mine) 
      throw new Exception("Couldn't get mutex"); 
     Console.WriteLine("Got mutex"); 
    } 
} 

Console.WriteLine("Finished"); 

これが終了したことがない、それはミューテックスの作成とラインに引っかかっています。 documentationは、例外をスローするか何かを返すべきだと述べていますが、ブロッキングについては言及していません。

または関連していない場合がありますいくつかの他の観察、:私たちは、実際のアプリケーションを実行し、 として別のインスタンスを起動する場合

  • 我々は、現在のユーザーを「偽装」場合、それはすぐに
  • を返します。異なるユーザー、すべてが意図どおりに動作する

おそらく、基本的なシステムリソースで何かが起こっているかもしれませんが、わかりませんでした。この作品を作るには?

更新: Hansのコメントによれば、私はWindows Defenderを無効にしようとしましたが、それは役に立ちませんでした。ここではそれがぶら下がっています場所のスタックトレースです:

[email protected]() 
    [email protected]() 
    mscorlib.ni.dll!719c1867() 
    [Frames below may be incorrect and/or missing, native debugger attempting to walk managed call stack] 
    mscorlib.ni.dll!719c1852() 
    [Managed to Native Transition] 
    mscorlib.dll!System.Threading.Mutex.CreateMutexHandle(bool initiallyOwned, string name, Microsoft.Win32.Win32Native.SECURITY_ATTRIBUTES securityAttribute, out Microsoft.Win32.SafeHandles.SafeWaitHandle mutexHandle) 
     mscorlib.dll!System.Threading.Mutex.MutexTryCodeHelper.MutexTryCode(object userData) 
    [Native to Managed Transition] 
    [Managed to Native Transition] 
    mscorlib.dll!System.Threading.Mutex.CreateMutexWithGuaranteedCleanup(bool initiallyOwned, string name, out bool createdNew, Microsoft.Win32.Win32Native.SECURITY_ATTRIBUTES secAttrs) 
    mscorlib.dll!System.Threading.Mutex.Mutex(bool initiallyOwned, string name, out bool createdNew, System.Security.AccessControl.MutexSecurity mutexSecurity) 
    mscorlib.dll!System.Threading.Mutex.Mutex(bool initiallyOwned, string name, out bool createdNew)  
    MutexImpersonationTest.exe!MutexImpersonationTest.Program.Main(string[] args) Line 16 
+0

非常に奇妙です。 FWIW、良い答えが得られない場合、最後の回避策は.netクラスを忘れ、P/Invokeを使用してWin32 APIを直接呼び出すことです。 –

答えて

6

ミューテックスを取得するコードが無限ループで立ち往生されており、私のテストでは、それはへの呼び出し内で100%に一つのコアをペッグているように見えますnew Mutex(...)

この理由は、フレームワークコードがWin32 CreateMutexの呼び出しを試み、「アクセスが拒否されました」というエラーが発生して、代わりにOpenMutexを呼び出そうとした場合です。 OpenMutex呼び出しが失敗し、mutexが存在しないことを示すエラーが返された場合、プロセス全体が再び繰り返されるため、mutexが存在しない場合は無限ループに陥ることになります。

CreateMutex documentationによると、これは基本的に正しいアプローチですが、アクセスはそれが原因既存のミューテックスに権限を設定するないだが拒否されましたし、最初のCreateMutexが失敗したときにケースを考慮していないようです。

私が試したときにうまくいったことの1つは、ミューテックス名の前に "Global \"という接頭辞を付けることでした。うまくいけば、これは適切な回避策です。

+0

グローバルミューテックスは実際にこのように作成できますが、すべてのユーザセッションでインスタンスが制限されるため、動作の劇的な変化になります。 –

+0

いいえ、catch(真)のコードはこちら(http:// referencesource)。 microsoft.com/#mscorlib/system/threading/mutex.cs9faa5b5e2b4c8f31)。 –

+1

@MártonMolnárセッション固有のミューテックスが必要な場合は、いくつかのオプションがあるようです。ミューテックスを作成する前にミューテックス*を作成し、権限を設定して偽装するユーザーにアクセスさせるか、グローバル\ "プレフィックスを使用しますが、セッションID(' Process。GetCurrentProcess()。SessionId')をミューテックスの名前に追加することで、グローバル名前空間に「セッションごと」のミューテックスを作成します。 – Iridium

関連する問題