安全异常:ECall方法必须打包到系统模块中。

38

我有一个类似下面的(C#)函数。

private static bool SpecialCase = false;

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

    Console.WriteLine();
}

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

当我在.NET Framework 4调试器中执行此操作时,该方法成功地将空行打印到控制台并返回。 当我在调试器外执行它时,它会抛出以下异常:

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

看起来异常是在JIT编译方法时抛出,而不是在调用InternalMethod时(如果有的话)抛出。是否有任何我可以做的事情(例如属性),告诉CLI要么不抛出SecurityException,要么延迟异常直到实际调用该方法?

关于使用案例的附注:当在Microsoft .NET Framework下运行时,SpecialCase字段实际上为false,在不同(特定)实现的CLI下运行时为true。 在Microsoft .NET Framework下运行时,对InternalMethod的调用实际上是无法访问的。


1
你能把它包装在一个普通的方法里吗? - SLaks
2
是的,调用像以下这样的包装器方法似乎可以避免异常。缺点是,这种做法会在已经复杂的算法中导致更加混乱的代码路径,因此如果有更清晰的解决方案,我更喜欢使用它。private static void InternalMethodWrapper() { InternalMethod(); } - Sam Harwell
顺便提一下,这个问题在.NET 4.5.2上也会出现,但是在两个框架中(两个框架都有相同的CLR)只有在“Release”模式下才会出现,您考虑过在“Debug”模式下工作吗? - Tamir Vered
我能找到的唯一信息是,错误消息是mscorrc.dll(Microsoft .NET Runtime资源)中id为8244的资源。 - Siderite Zackwehdex
2个回答

3
在您的类声明中添加属性[ComImport]

2
您可能需要检查编译器指令作为一种可能的选项。 与使用运行时“if”不同,这将确定调用是否包含在编译代码中,而不是始终将其编译到代码中并尝试在运行时确定是否调用它(基于您的分析太晚了)。
您的用例似乎是测试/验证场景,这意味着除非在实际进行内部调用时,否则您不需要将其编译到代码中。
请注意,如果您的用例涉及非.NET运行时,则应提供更多信息,因为这可能会大大改变正确答案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接