2012-07-01 129 views
34

我有一個(C#)函數類似於以下內容。SecurityException:必須將ECall方法打包到系統模塊中

private static bool SpecialCase = false; 

public void Foo() 
{ 
    if (SpecialCase) 
    { 
     InternalMethod(); 
     return; 
    } 

    Console.WriteLine(); 
} 

[MethodImpl(MethodImplOptions.InternalCall)] 
private static extern void InternalMethod(); 

當我執行這與調試器內的.NET框架4,該方法成功打印空白行到控制檯,然後返回。當我執行它在調試器外部,它拋出異常以下消息:

System.Security.SecurityException: ECall methods must be packaged into a system module. 

似乎當JIT編譯器編譯的方法,而不是當(如果)InternalMethod被調用以拋出異常。有什麼我可以做的(例如屬性)告訴CLI要麼不拋出SecurityException,要麼延遲異常直到實際調用該方法爲止?

使用案例的附註:使用Microsoft .NET Framework運行時,SpecialCase字段實際上是錯誤的,在CLI的另一個(特定)實現下運行時,該字段爲true。在Microsoft .NET Framework下運行時,對InternalMethod的調用實際上無法訪問。

+0

你可以用普通的方法包裝它嗎? – SLaks

+1

是的,看起來像調用下面的包裝器方法可以避免這種異常。缺點是這種做法會導致在已經複雜的算法中出現更多令人困惑的代碼路徑,所以如果可以找到更清晰的解決方案,我更喜歡它。 'private static void InternalMethodWrapper(){InternalMethod(); }' –

+0

順便說一句,它也發生在'.NET 4.5.2'上,但是在兩個框架中(兩個框架都有相同的'CLR')只在'Release'而不是'Debug'中,你認爲是在'Debug'模式下工作? –

回答

1

添加屬性[ComImport]到類聲明

2

你可能要檢查的compiler directives as a possible option。 與使用運行時「if」不同,它將確定調用是否包含在編譯代碼中,而不是始終將其編譯到代碼中,並試圖確定是否在運行時調用它(這也是如此遲到,根據你的分析)。

您的用例看起來像一個測試/驗證場景,這意味着您不需要將其編譯到代碼中,除非實際進行內部調用。

請注意,如果您的用例涉及非.NET運行時,您應該提供更多信息,因爲這可能會徹底改變正確的答案。