Reputation: 14787
I have been following this article to generate a dynamic assembly as follows:
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.
Here is what I know about the code above:
private static int Main (string [])
.METHOD:
Console.WriteLine
with the arguments taken from the stack.Console.WriteLine
again using EmitWriteLine
.CRASH:
Ignore the filename on the image. It would be MyDynamicAssembly.exe
per the code above.
Any pointers on what's going wrong here would be appreciated.
Upvotes: 3
Views: 949
Reputation: 941457
You'll have a lot more tough debugging jobs ahead of you beyond this one. You basically only ever get two exit codes. -532462766 or 0xe0434352 is the infamous "CCR" exception. The CLR died trying to load the assembly and can't perform the normal exception handling logic. You of course want to make sure that your generated IL is correct by testing it in-process before you try to run it stand-alone in a separate process. You'll at least have a debugger available that way.
The other one is -532459699 or 0xe0434f4d, the normal "COM" exception. Produced when the code threw a plain .NET exception and it wasn't handled because of a lack of try/catch and no AppDomain.UnhandledException event handler. You'll have to make-do without a stack trace and can only reverse-engineer the location where the exception was thrown with the hints in this answer.
Very punishing trouble-shooting of course, you basically do not ever want to do this. At least consider loading the code in another AppDomain so you stand a chance to produce a diagnostic and recover. It can still be in another process by writing a small "host" program that creates the appdomain and loads the assembly and generates a diagnostic. Also provides you with a way to use the debugger.
Upvotes: 2
Reputation: 14787
Finally got it to work by changing the module builder cell to overload:
var builderModule = builderAssembly.DefineDynamicModule("MyDynamicAssembly", "MyDynamicAssembly.exe", false);
Upvotes: 1