创建一个.EXE,从.dll调用一个函数

时间:2015-10-25 12:31:17

标签: c# reflection emit

所以我有一个.dll与一个函数(静态或实例,我可以改变它,仍然有效),我想创建一个以Main作为入口点的Exe,它读取命令行,并调用函数来自.dll

这是我试图打电话的方法

 public static void Add(String a, String b)
 {
  Console.WriteLine( "{0} + {1}=  {2}", a, b , a+b);
 }

- 我加载dll程序集,并获取具有我想要的功能的类型

        Assembly asmLoaded = Assembly.LoadFrom(nameDLL);
        Type baseType = asmLoaded.GetType(typeName);

- 为新的Exe

创建新的程序集,模块和类型
AssemblyName aName = new AssemblyName("AppAsm");

        AssemblyBuilder ab =
        AppDomain.CurrentDomain.DefineDynamicAssembly(
            aName,
            AssemblyBuilderAccess.Save);

        ModuleBuilder mb =
        ab.DefineDynamicModule("AppMod", typeName + methodName + ".exe");

        TypeBuilder tb = mb.DefineType("AppType", TypeAttributes.Public);

- 从我要调用的方法获取methodInfo,并为后面的Emit获取其参数Types [](Opcodes.Call,..);

- 然后我将方法“Main”定义为入口点

 MethodBuilder metb = tb.DefineMethod("Main", MethodAttributes.Public |
            MethodAttributes.Static, null, new Type[] { typeof(String[])});
 ab.SetEntryPoint(metb);

- 使用ildasm,我试图做这个部分,生成IL

 ILGenerator il = metb.GetILGenerator();
 for (int i = 0; i <paramTypes.Length; ++i)
        {
            il.Emit(OpCodes.Ldarg_0); // get the String[], in 0 cause its static
            il.Emit(OpCodes.Ldc_I4,i);
            il.Emit(OpCodes.Ldelem_Ref);
            il.Emit(OpCodes.Stloc, i);
        }         
        il.Emit(OpCodes.Ldloc, 0);
        il.Emit(OpCodes.Ldloc, 1);
        il.EmitCall(OpCodes.Call, wantedMethodInfo, paramTypes);
        il.Emit(OpCodes.Ret);

- 最后我创建了Type,并保存了assemblyBuilder

tb.CreateType();
ab.Save(typeName + methodName + ".exe");

当然它不起作用,xD 当我运行用某些值生成的exe时,它会抛出 System.InvalidProgramException:Common Languafe Runtime检测到无效程序。在AppTYpe.Main(String [])中 我想我应该是Pop,有些东西不在堆栈中,但不确定。

1 个答案:

答案 0 :(得分:1)

我会使用表达式树来生成这个(简单)Main函数。您可以使用CompileToMethod方法将表达式树转换为MethodBuilder

此外,调试方法是运行PEVerify。

无法告诉您IL的具体位置是错误的,因为我无法看到您想要调用的方法。你需要扔掉它。使用表达式树。

还有一个奇怪的选择是你根本就在使用当地人。你可以这样做:

ldelem 0
ldelem 1
ldelem ...
call
ret

在伪代码中。