使用System.Reflection.Emit在Windows.Forms中显示一个MessageBox

4
我正在尝试使用ilgenerator.emit创建一个msgbox,但在运行代码时出现异常:

来自调用目标的异常

这是我的代码:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim assemblyName As AssemblyName = New AssemblyName("SamAsm")
    Dim assemblyBuilder As AssemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave)

    'Creating module
    Dim moduleBuilder As ModuleBuilder = assemblyBuilder.DefineDynamicModule("SamAsm.exe")

    Creating class file
    Dim typeBuilder As TypeBuilder = moduleBuilder.DefineType("SamAsmType", TypeAttributes.Public Or TypeAttributes.Class)

    Creating Main Method
    Dim methodBuilder1 As MethodBuilder = typeBuilder.DefineMethod("Main", MethodAttributes.Static Or MethodAttributes.Public, GetType(Void), New System.Type() {GetType(String)})

    'Generating Code for method builder in IL
    Dim ilGenerator As ILGenerator = methodBuilder1.GetILGenerator
    ilGenerator.Emit(OpCodes.Ldstr, "test")
    ilGenerator.EmitCall(OpCodes.Call, GetType(System.Windows.Forms.MessageBox).GetMethod("Show", {GetType(String)}), {GetType(String)})
    ilGenerator.Emit(OpCodes.Ret)

    'Creating Class object (type) and accessing main method
    Dim SamAsmType As Type = typeBuilder.CreateType
    SamAsmType.GetMethod("Main").Invoke(Nothing, New String() {Nothing})

    'Creating Entry Point and saving assembly
    assemblyBuilder.SetEntryPoint(methodBuilder1, PEFileKinds.WindowApplication)
    assemblyBuilder.Save("SamAsm.exe")
End Sub

首先,用C#或VB.NET编写代码,然后使用ildasm.exe查看IL。 - Hans Passant
1个回答

4

在从Sub/void函数返回时,您必须确保堆栈为空。

Show方法返回DialogResult,因此您需要调用Pop从堆栈中删除DialogResult

...
ilGenerator.EmitCall(OpCodes.Call, GetType(System.Windows.Forms.MessageBox).GetMethod("Show", {GetType(String)}), {GetType(String)})
ilGenerator.Emit(OpCodes.Pop) ' remove the return value of Show from the stack
ilGenerator.Emit(OpCodes.Ret)
...

然而,您总是可以使用 peverify 来追踪您动态创建的程序集中的错误。

因此,在您的情况下,对 SamAsm.exe 运行 peverify 将会给您以下错误:

[IL]: Error: [c:\yourpath\SamAsm.exe : SamAsmType::Main][offset 0x0000000A] Stack must be empty on return from a void function. 1 Error(s) Verifying SamAsm.exe


非常感谢Dominic!我可以问另外一件事吗?(我对emit很陌生)..如何使用brfalse进行if检查呢?因为像brfalse或brtrue这样的指令会指向另一个指令,我不知道该怎么做!谢谢。 - user1872492

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