【问题标题】:DynamicMethod - Common language runtime detected an invalid programDynamicMethod - 公共语言运行时检测到无效程序
【发布时间】:2017-05-05 18:38:52
【问题描述】:

所以我尝试使用 ilgenerator 通过动态方法从外部 DLL 调用方法。

delegate void Write(string text);
static void Main(string[] args)
{
    byte[] bytes = File.ReadAllBytes(@"externmethod.dll");
    var assembly = Assembly.Load(bytes);
    var method = assembly.GetTypes()[0].GetMethod("Write");
    var dynamicMethod = new DynamicMethod("Write", typeof(void), new Type[] { typeof(string) });
    var ilGenerator = dynamicMethod.GetILGenerator();
    ilGenerator.EmitCall(OpCodes.Call, method, null);
    var delegateVoid = dynamicMethod.CreateDelegate(typeof(Write)) as Write;
    delegateVoid("test");
    Console.ReadLine();
}

以及 DLL 代码:

using System;
class program
{
    public static void Write(string text)
    {
        Console.WriteLine(text);
    }
}

但我收到了这个奇怪的错误:

在 test.exe 中发生了“System.InvalidProgramException”类型的未处理异常
附加信息:公共语言运行时检测到无效程序。

我不知道我做错了什么??

【问题讨论】:

    标签: c# invoke dynamicmethod opcodes


    【解决方案1】:

    您的委托 delegate void Write(string text); 接受字符串作为参数,因此您需要在发出 call 之前执行此操作:

    ilGenerator.Emit(System.Reflection.Emit.OpCodes.Ldstr, "this is test");
    

    而且你必须在方法结束时返回,所以你需要这样做:

    ilGenerator.Emit(System.Reflection.Emit.OpCodes.Ret);
    

    完整代码:

    var method = assembly.GetTypes()[0].GetMethod("Write");
    var dynamicMethod = new DynamicMethod("Write", typeof(void), new Type[] { typeof(string) });
    var ilGenerator = dynamicMethod.GetILGenerator();
    ilGenerator.Emit(System.Reflection.Emit.OpCodes.Ldstr, "this is test");
    ilGenerator.Emit(System.Reflection.Emit.OpCodes.Call, method);
    ilGenerator.Emit(System.Reflection.Emit.OpCodes.Ret);
    var delegateVoid = dynamicMethod.CreateDelegate(typeof(Write)) as Write;
    delegateVoid("test");
    

    更新:我注意到您想将参数发送到方法而不是

    ilGenerator.Emit(System.Reflection.Emit.OpCodes.Ldstr, "this is test");
    

    写这个

    ilGenerator.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
    

    然后您发送到这里的delegateVoid("test"); 将打印出来。

    关于访问限制,如果您不能将Program 类公开,您可以像这样定义您的DynamicMethod 以获得访问权限:

    var dynamicMethod = new DynamicMethod("Write", typeof(void), new[] { typeof(string) }, assembly.GetTypes()[0]);
    

    【讨论】:

    • 我试过你的代码,但它给了我另一个错误;
    • 错误消息:附加信息:尝试通过方法 'DynamicClass.Write(System.String)' 访问方法 'program.Write(System.String)' 失败。
    • @JustusBosschieter 这是MethodAccessException。使Programpublic
    • 您可以在创建 DynamicMethod 时使用 skipVisibilityCheck = true 而不是更改程序范围。
    猜你喜欢
    • 2018-02-17
    • 1970-01-01
    • 2011-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-08
    • 2022-01-25
    相关资源
    最近更新 更多