c#-使用Reflection.Emit创建的动态程序集崩溃,退出代码为-532462766
作者:互联网
我一直按照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的公共静态类.
>它在此类中创建一个带有签名的私有静态int Main(字符串[])的方法.
>将此方法设置为入口点,并将程序集配置为控制台应用程序.
>它将程序集写为ILOnly,这与处理器体系结构无关.
>它将程序集映像配置为我正在运行的i386(使用Intel处理器的Win7 32位).
方法:
>将字符串文字引用推入堆栈.
>使用从堆栈中获取的参数调用Console.WriteLine.
>使用EmitWriteLine再次调用Console.WriteLine.
>将0作为Int32推入堆栈作为返回值.
>返回.
崩溃:
忽略图像上的文件名.根据上面的代码,它将是MyDynamicAssembly.exe.
任何在这里出了什么问题的指针将不胜感激.
解决方法:
除此以外,您还将面临更多艰巨的调试工作.您基本上只会获得两个退出代码. -532462766或0xe0434352是臭名昭著的“ CCR”异常. CLR在尝试加载程序集时死亡,无法执行常规的异常处理逻辑.您当然想通过在过程中对其进行测试来确保生成的IL是正确的,然后再尝试在单独的过程中独立运行它.您至少将以这种方式使用调试器.
另一个是-532459699或0xe0434f4d,这是正常的“ COM”异常.当代码抛出普通的.NET异常并且由于缺少try / catch且没有AppDomain.UnhandledException事件处理程序而无法对其进行处理时,生成该代码.您必须在没有堆栈跟踪的情况下进行工作,并且只能对通过this answer中的提示引发异常的位置进行反向工程.
当然,非常麻烦的排除故障,您基本上都不希望这样做.至少考虑将代码加载到另一个AppDomain中,这样您就有机会进行诊断并恢复.通过编写一个小的“主机”程序来创建应用程序域并加载程序集并生成诊断,它仍然可以处于另一个过程中.还为您提供了一种使用调试器的方法.
标签:reflection-emit,reflection,c,net,dynamic-assemblies 来源: https://codeday.me/bug/20191121/2051954.html