2017-09-22 55 views
0

我正在爲某些自定義需求構建.Net Profiler。.NET Profiler進入/離開函數掛鉤不會在異常情況下調用

我想掛鉤在輸入和離開一些特定的方法。爲了達到這個目的,我嘗試了兩種方法。

  1. IL重寫 - 我能夠在兩個地方注入自定義代碼。它已成功注入並調用自定義代碼。我也能夠得到輸入參數'this'並返回值。在Enter處注入並不困難。然而,在Leave中注入很複雜,因爲在方法中可能會有多個地方返回。我必須在寫入return語句的每個地方注入代碼。

    這有點複雜,但有點可行。但是,如果有任何異常,執行沒有達到返回語句,因此我的注入代碼沒有被調用。

  2. 根據給出的樣本代碼here訂閱Enter /通過SetEnterLeaveFunctionHooks2ICorProfilerInfo2中。

在這兩種情況下,在方法中發生異常的情況下,不會調用Leave。

如何處理?我想要在所有情況下的返回值。如果有例外,我應該知道有一個例外;我會考慮爲'沒有回報價值'。也許,我可能也需要異常細節。

下面是一個示例方法。我想在Enter和Leave for GetString方法上掛鉤。它有多個回報。我能夠在正常情況下捕獲返回值。但是,如果發生異常,執行立即停止,並且由於返回時的鉤子沒有被調用。

public int GetInt() 
    { 
     //int retVal = 10; 
     int retVal = 1010; 
     //throw new Exception("test"); 
     return retVal; 
    } 

    public string GetString() 
    { 
     var retunValue = "Return string "; 

     if (GetInt() > 100) 
     { 
      retunValue += " inside IF > 100"; 
      return retunValue; 
     } 

     return retunValue + " at last return"; 
    } 
+0

很難理解這一點。如果你打算使用profiler api來重寫IL,那麼你最好在代碼開始執行之前這麼做。換句話說,您需要JITCompilationStarted回調。如果你使用SetEnterLeaveFunctionHooks2來實現,那麼死亡就會被施放,IL已經得到了解決,並且改變它不會有任何影響。有了另外一個明顯的優點,那就是當你用JITCompilationStarted完成時,你不必再擔心異常。 –

+0

@HansPassant,對於IL Rewrite,我在ModuleLoadFinished回調中執行,一切正常,我的代碼被注入並在正常執行流程中調用。但是,如果我在GetValue方法中取消註釋拋出異常語句,它不會被調用(由於顯而易見的原因)。 GetValue僅僅是示例代碼插圖的目的,在實際場景中異常隨時可以得到。 – Hitesh

回答

1

要使用IL重寫時得到異常通知,您需要注入try-finally或try-catch-throw。由於ret指令在try塊內無效,因此您需要用leave指令替換它們,該指令在插入的異常處理程序後分支到指令並從那裏返回。

另一種選擇是在您致電SetEventMask時加入COR_PRF_MONITOR_EXCEPTIONS,並聽取ExceptionUnwindFunctionEnterExceptionUnwindFunctionLeave回調。這些回調不包括拋出的異常。你可能trackExceptionThrown的例外,但這可能會誤導,當一個異常離開一個過濾塊,因爲運行時將它視爲返回false並繼續以前的異常,但IIRC,沒有回調來表明這種情況發生時。

+0

感謝Brian回覆。你能提供一些關於如何注入try/catch/finally塊的幫助嗎? – Hitesh

+0

對於另一種方法,我可以處理ExceptionUnwindFunctionEnter/Leave方法。但是,正如你所提到的,它沒有提供例外細節。您能否提供更多信息,我如何獲得例外情況? – Hitesh

+1

異常處理程序在傳遞給SetILFunctionBody的函數體的數據部分中指定。格式的詳細信息可以在[EMCA-335](https://www.ecma-international.org/publications/standards/Ecma-335.htm)中找到。分區II第25.4節 –

相關問題