2013-03-15 89 views
5

我的C#代碼使用模擬由通過P調用Win32函數/調用爲什麼來自模擬代碼的異常未被捕獲?

internal class Win32Native 
{ 
    [DllImport("advapi32.dll", SetLastError = true)] 
    public static extern int ImpersonateLoggedOnUser(IntPtr token); 

    [DllImport("advapi32.dll", SetLastError = true)] 
    public static extern int RevertToSelf(); 
} 

try { 
    var token = obtainTokenFromLogonUser(); 
    Win32Native.ImpersonateLoggedOnUser(token); 
    throw new Exception(); // this is for simulation 
    Win32Native.RevertToSelf() 
} catch(Exception e) { 
    LogException(e); 
    throw; 
} 

還我AppDomain.CurrentDomain.UnhandledException處理程序安裝還記錄所有未處理的異常。

我敢肯定,記錄異常的代碼在使用和不使用模擬時都可以正常工作。

現在的問題是,在上面的代碼中,它看起來像沒有輸入catchUnhandledException也沒有被調用。事件查看器中的條目是唯一的異常跟蹤。

如果我添加一個finally這樣的:

try { 
    var token = obtainTokenFromLogonUser(); 
    Win32Native.ImpersonateLoggedOnUser(token); 
    try { 
     throw new Exception(); // this is for simulation 
    } finally { 
     Win32Native.RevertToSelf() 
    } 
} catch(Exception e) { 
    LogException(e); 
    throw; 
} 

則異常無論從catchUnhandledException處理記錄好。

發生了什麼事?被模擬的線程是否阻止了常規的異常處理?

+0

如果你在'LogException'上放置一個斷點:你到那裏了嗎? – 2013-03-15 10:02:18

+0

@MarcGravell:我不知道,沒有調試器在哪裏複製。我意識到'LogException()'本身可能存在一些問題,但到目前爲止,它所依賴的代碼都可以正常工作,並且不會被模擬。 – sharptooth 2013-03-15 10:04:12

+0

在這裏做一個猜測:因爲.NET會跟蹤執行上下文,所以異常處理可能會意識到上下文已經改變,並且正在阻止異常處理程序執行,除非首先執行回覆。如果代碼與模擬用戶一起運行,則不這樣做會導致特權提升...... – 2013-03-15 12:26:11

回答

3

沒有看到LogException的代碼,我不能確定,但​​它可能是,無論你在那裏做的是在模擬/登錄用戶的情況下這樣做,並且該用戶沒有用戶無論你在做什麼都有權利做例如寫入一個文件等,然後代碼崩潰在那一刻。事實上,你的代碼只有在你「恢復自我」之後才能起作用,這似乎證明了這一點。

所以我想說的是,你的異常實際上是被catch捕獲的,但是由於它試圖在不正確的用戶上下文中工作,LogException失敗了。

要測試這一點,在LogException中,嘗試在嘗試任何日誌記錄之前強制當前上下文爲「Self」,並查看第一個片段是否現在開始工作。

1

原來問題出在日誌代碼上。在某些時候,我們添加了檢索當前進程開始時間(Process.StartTime)的代碼,並且從模擬線程調用該代碼時產生Access denied

Access is denied 
System.ComponentModel.Win32Exception 
at System.Diagnostics.Process.GetProcessHandle(Int32 access, Boolean throwIfExited) 
at System.Diagnostics.Process.GetProcessTimes() 
at System.Diagnostics.Process.get_StartTime() 
//our logging code here 

記錄代碼也叫System.Diagnostics.Trace.WriteLine()之前Process.StartTime調用代碼,並通過「跟蹤偵聽器」成功地寫道,只寫通過後者的代碼失敗。

因此,在有或沒有假冒的情況下捕捉例外情況沒有區別。甚至可以安裝一個異常過濾器,以便在可能導致權限提升的模擬代碼的安全上下文中調用它。 Details for the latter here