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:
- It is creating a dynamic assembly as Save only.
- The assembly name, module name and output PE name are all different (I'm assuming this is not a problem).
- It creates a public static class called Program.
- It creates a single method in this class with signature
private static int Main (string [])
. - It sets this method as an entry point and configures the assembly to be a console app.
- It writes the assembly as ILOnly which is processor architecture agnostic.
- It configures the assembly image as i386 which is what I'm running on (Win7 32 bit with an Intel processor).
METHOD:
- Pushes a string literal reference to the stack.
- Calls
Console.WriteLine
with the arguments taken from the stack. - Calls
Console.WriteLine
again usingEmitWriteLine
. - Pushes 0 as an Int32 to the stack as a return value.
- Returns.
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.