3

我一直在关注这篇文章来生成一个动态程序集,如下所示:

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 推入堆栈作为返回值。
  • 返回。

碰撞:

忽略图像上的文件名。这将MyDynamicAssembly.exe按照上面的代码。 应用崩溃信息

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

4

2 回答 2

2

除了这个之外,你还有更多艰巨的调试工作。你基本上只会得到两个退出代码。-532462766 或 0xe0434352 是臭名昭著的“CCR”异常。CLR 在尝试加载程序集时死亡,无法执行正常的异常处理逻辑。您当然希望通过在进程中测试生成的 IL 来确保它是正确的,然后再尝试在单独的进程中独立运行它。您至少可以通过这种方式使用调试器。

另一个是 -532459699 或 0xe0434f4d,正常的“COM”异常。当代码抛出一个普通的 .NET 异常并且由于缺少 try/catch 并且没有 AppDomain.UnhandledException 事件处理程序而未处理时产生。您将不得不在没有堆栈跟踪的情况下进行处理,并且只能使用此答案中的提示对引发异常的位置进行反向工程。

当然,非常惩罚故障排除,你基本上不想这样做。至少考虑将代码加载到另一个 AppDomain 中,这样您就有机会进行诊断和恢复。通过编写一个小的“主机”程序,它仍然可以在另一个进程中,该程序创建 appdomain 并加载程序集并生成诊断。还为您提供了一种使用调试器的方法。

于 2014-07-24T08:49:16.837 回答
1

最后通过将模块构建器单元更改为重载来使其工作:

var builderModule = builderAssembly.DefineDynamicModule("MyDynamicAssembly", "MyDynamicAssembly.exe", false);
于 2014-07-24T03:12:22.993 回答