Я пытаюсь создать файл .exe, и этот файл должен вызывать функцию, которая размещена в другой DLL.Я могу правильно загрузить библиотеку DLL, и на тип и метод ссылаются правильно, но при попытке вызвать метод Main возникает исключение:
Common Language Runtime обнаружил недопустимую программу.
Я знаю, что когда я пытаюсь вызвать метод из другой DLL, это вызывает ошибку, потому что я пытаюсь запустить эту программу без этой инструкции, и не было никакого исключения выброса.Я собираюсь поместить весь код здесь (это для целей изучения).
static void Main() {
String path=createTestMethodDLL()+"\\Testing.dll";
AssemblyName asmName = new AssemblyName();
asmName.Name = "HelloReflectionEmit";
AppDomain appDom = Thread.GetDomain();
// Create AssemblyBuilder with "RunAndSave" access
AssemblyBuilder asmBuilder = appDom.DefineDynamicAssembly(asmName,
AssemblyBuilderAccess.RunAndSave);
// Assembly filename
string filename = asmName.Name + ".exe";
// Create ModuleBuilder object
ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule(
asmName.Name, filename);
// Define "public class Hello.Emitted"
//
TypeBuilder typeBuilder = modBuilder.DefineType("Hello.Emitted",
TypeAttributes.Public | TypeAttributes.Class);
// Define "public static int Main(string[] args)"
//
MethodBuilder methBuilder = typeBuilder.DefineMethod("Main",
MethodAttributes.Public |
MethodAttributes.Static,
typeof(int),
new Type[] { typeof(string[]) });
MethodBuilder methBuilder2 = typeBuilder.DefineMethod("test",
MethodAttributes.Public |
MethodAttributes.Static);
ILGenerator ilGen = methBuilder.GetILGenerator();
ILGenerator ilGen2 = methBuilder2.GetILGenerator();
ilGen2.Emit(OpCodes.Ldstr, "test method!");
ilGen2.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string[]) }));
ilGen2.Emit(OpCodes.Ret);
// Define a call to System.Console.WriteLine, passing "Hello World"
var DLL=Assembly.LoadFile(path);
Type [] ty=DLL.GetExportedTypes();
ilGen.Emit(OpCodes.Ldstr, "Hello, World!");
ilGen.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string[]) }));
ilGen.EmitCall(OpCodes.Call,methBuilder2,new Type[] { });
//problem Down here//
ilGen.EmitCall(OpCodes.Call, ty[0].GetMethod("testFunction"),new Type[] {});
ilGen.Emit(OpCodes.Ldc_I4_0);
ilGen.Emit(OpCodes.Ret);
asmBuilder.SetEntryPoint(methBuilder, PEFileKinds.ConsoleApplication);
// Save assembly to file
asmBuilder.Save(filename);
ReflectOnAssembly(asmName, asmBuilder, "Main", "Hello.Emitted");
appDom.ExecuteAssembly(filename);
Console.WriteLine("Finished executing {0}", asmName.Name);
Console.ReadLine();
LoadAssembly(filename);
}
private static String createTestMethodDLL() {
AssemblyName asmName = new AssemblyName();
asmName.Name = "Testing";
AppDomain appDom = Thread.GetDomain();
// Create AssemblyBuilder with "RunAndSave" access
AssemblyBuilder asmBuilder = appDom.DefineDynamicAssembly(asmName,
AssemblyBuilderAccess.RunAndSave);
// Assembly filename
string filename = asmName.Name + ".dll";
// Create ModuleBuilder object
ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule(
asmName.Name, filename);
// Define "public class Hello.Emitted"
//
TypeBuilder typeBuilder = modBuilder.DefineType("ConsoleApp1.Testing",
TypeAttributes.Public | TypeAttributes.Class);
// Define "public static int Main(string[] args)"
//
MethodBuilder methBuilder = typeBuilder.DefineMethod("testFunction",
MethodAttributes.Public |
MethodAttributes.Static);
ILGenerator ilGen = methBuilder.GetILGenerator();
ilGen.Emit(OpCodes.Ldstr, "testing!");
ilGen.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string[]) }));
ilGen.Emit(OpCodes.Ldc_I4_0);
ilGen.Emit(OpCodes.Ret);
// Create type
Type t = typeBuilder.CreateType();
// Reflect
//ReflectOnAssembly(asmName, asmBuilder,"testFunction", "ConsoleApp1.Testing");
asmBuilder.SetEntryPoint(methBuilder, PEFileKinds.ConsoleApplication);
// Save assembly to file
asmBuilder.Save(filename);
//LoadAssembly(filename);
Assembly asm = Assembly.GetExecutingAssembly();
return System.IO.Path.GetDirectoryName(asm.Location);
}
private static void ReflectOnAssembly(AssemblyName asmName, AssemblyBuilder asmBuilder,String methodName,String typeName) {
Console.WriteLine("Now, use reflection on assembly {0}:", asmName.Name);
foreach (Type type in asmBuilder.GetTypes()) {
Console.WriteLine("Type {0}", type);
foreach (MethodInfo mi in type.GetMethods(BindingFlags.Public
| BindingFlags.NonPublic
| BindingFlags.Instance
| BindingFlags.Static)) {
Console.WriteLine("Method {0}", mi.ToString());
}
Console.WriteLine("Invoking Main:");
MethodInfo mainMethod = asmBuilder.GetType(typeName).GetMethod(methodName);
if (mainMethod != null)
// First param = this, second param = method parameters
mainMethod.Invoke(null, new object[1] { null });
}
}
private static void LoadAssembly(string filename) {
Assembly assembly = Assembly.LoadFrom(filename);
// Get public and non public types from assembly
Type[] types = assembly.GetTypes();
foreach (Type t in types) {
Console.WriteLine(t.Name);
}
}