1
我正在C#中编写一个连接语言,目前它被解释,但我想要采取下一步:编译。首先,我尝试写一个简单的“你好,世界!”程序发射器使用System.Reflection.Emit。该代码工作没有任何的Emit异常,但是当我运行生成的“TEST.EXE”的文件,它抛出我曾试着用搜索引擎寻找答案异常Reflection.Emit:AssemblyBuilder.SetEntryPoint不设置入口点
Unhandled Exception: System.MissingMethodException: Entry point not found in assembly 'IL_Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
,但无济于事。也许这里有人可以帮助我? (请)我写的代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Reflection.Emit;
using System.IO;
using System.Diagnostics;
namespace ILCompileTest
{
class Program
{
static void Main(string[] args)
{
const string ASSEMBLY_NAME = "IL_Test";
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName(ASSEMBLY_NAME), AssemblyBuilderAccess.Save);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(
ASSEMBLY_NAME);
TypeBuilder typeBuilder = moduleBuilder.DefineType("Program",
TypeAttributes.Class | TypeAttributes.Public);
MethodBuilder methodBuilder = typeBuilder.DefineMethod(
"Main", MethodAttributes.Public | MethodAttributes.Static,
typeof(void), new Type[] { typeof(string[]) });
ILGenerator gen = methodBuilder.GetILGenerator();
gen.Emit(OpCodes.Ldstr, "Hello, World!");
gen.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
gen.Emit(OpCodes.Ldc_I4_1);
gen.Emit(OpCodes.Call, typeof(Console).GetMethod("ReadKey", new Type[] { typeof(bool) }));
assemblyBuilder.SetEntryPoint(methodBuilder, PEFileKinds.ConsoleApplication);
File.Delete("test.exe");
assemblyBuilder.Save("test.exe");
Process.Start("test.exe");
}
}
}
所以,问题是:我怎么可以在进入点设置为Main方法我定义?
Thanks!这解决了它!我还发现,我需要Opcodes.Pop Console.ReadKey的返回值,并有一个Opcodes.Ret命令,以使整个事情工作。 – feralin 2013-03-24 19:41:28
你知道为什么ModuleBuilder想要文件名吗?它甚至必须与我传递给AssemblyBuilder.Save()的值相同吗? – feralin 2013-03-24 19:42:22
我认为这与DefineDynamicModule的重载选择差有关 - 根据MSDN,两个重载创建瞬态,两个创建持久模块。文件名必须相同,否则应用程序也会失败。在两个地方指定文件名可以从多个模块/文件中创建程序集。 – Alexander 2013-03-25 07:00:41