使用Reflection.Emit创建的动态程序集崩溃,退出代码为-532462766

时间:2014-07-24 01:56:26

标签: c# .net reflection reflection.emit dynamic-assemblies

我一直关注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.

以下是我对上述代码的了解:

  • 它正在创建一个动态程序集“仅保存”。
  • 程序集名称,模块名称和输出PE名称都不同(我假设这不是问题)。
  • 它创建一个名为Program的公共静态类。
  • 它在此类中创建一个带有签名private static int Main (string [])的方法。
  • 它将此方法设置为入口点,并将程序集配置为控制台应用程序。
  • 它将程序集写为ILOnly,它与处理器体系结构无关。
  • 它将程序集映像配置为i386,这是我正在运行的(带有Intel处理器的Win7 32位)。

方式:

  • 将字符串文字引用推送到堆栈。
  • 使用从堆栈中获取的参数调用Console.WriteLine
  • 使用Console.WriteLine再次致电EmitWriteLine
  • 将0作为Int32推送到堆栈作为返回值。
  • 返回。

CRASH:

忽略图像上的文件名。根据上面的代码,它将是MyDynamicAssembly.exeApp crash info

任何关于这里出了什么问题的指示都将不胜感激。

2 个答案:

答案 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);