我一直关注this article生成动态程序集,如下所示:
var directory = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.Desktop));
var file = new FileInfo(Path.Combine(directory.FullName, @"MyDynamicAssembly.exe"));
var domain = AppDomain.CurrentDomain;
var name = new AssemblyName("Namespace.With.Dots");
var builderAssembly = domain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Save, directory.FullName);
var builderModule = builderAssembly.DefineDynamicModule("Namespace.With.Dots.Temp.exe");
var builderType = builderModule.DefineType("Program", TypeAttributes.Class | TypeAttributes.Public, typeof(object));
var builderMethod = builderType.DefineMethod("Main", MethodAttributes.Private | MethodAttributes.Static, typeof(int), new Type [] { typeof(string []) });
var generator = builderMethod.GetILGenerator();
generator.Emit(OpCodes.Ldstr, "Hello, World!");
generator.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type [] { typeof(string) }));
generator.EmitWriteLine("Hello again.");
generator.Emit(OpCodes.Ldc_I4, 0);
generator.Emit(OpCodes.Ret);
builderAssembly.SetEntryPoint(builderMethod, PEFileKinds.ConsoleApplication);
builderAssembly.Save(file.Name, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
var process = Process.Start(file.FullName); // Crashes with image below.
var result = process.WaitForExit();
var exitCode = process.ExitCode; // -532462766.
以下是我对上述代码的了解:
private static int Main (string [])
的方法。方式:
Console.WriteLine
。Console.WriteLine
再次致电EmitWriteLine
。CRASH:
忽略图像上的文件名。根据上面的代码,它将是MyDynamicAssembly.exe
。
任何关于这里出了什么问题的指示都将不胜感激。
答案 0 :(得分:2)
除此之外,你将面临更多艰难的调试工作。你基本上只得到两个退出代码。 -532462766或0xe0434352是臭名昭着的" CCR"例外。 CLR在尝试加载程序集时死亡,无法执行正常的异常处理逻辑。您当然希望通过在进程中测试生成的IL是正确的,然后再尝试在单独的进程中独立运行它。您至少可以通过这种方式使用调试器。
另一个是-532459699或0xe0434f4d,正常" COM"例外。当代码抛出一个普通的.NET异常并且由于缺少try / catch而没有AppDomain.UnhandledException事件处理程序而没有处理时生成。您必须在没有堆栈跟踪的情况下进行make-do,并且只能使用this answer中的提示对引发异常的位置进行反向工程。
非常严厉的故障排除当然,你基本上不想要这样做。至少考虑在另一个AppDomain中加载代码,这样您就有机会生成诊断并进行恢复。通过写一个小的主机"它仍然可以在另一个过程中。创建appdomain并加载程序集并生成诊断的程序。还为您提供了一种使用调试器的方法。
答案 1 :(得分:1)
最后通过将模块构建器单元格更改为重载来实现它:
var builderModule = builderAssembly.DefineDynamicModule("MyDynamicAssembly", "MyDynamicAssembly.exe", false);