Browsing articles from "February, 2011"

Dynamically Creating .NET Assembly with System.Reflection and Emit

Feb 10, 2011   //   by Ramas   //   Blog, Programming  //  No Comments

While creating DeleteAfterRunning application which allows to build self-deleting executable files, I come across System.Reflection class in .NET for creating assemblies in the run-time. All .NET assemblies are made from IL code which you can examine using any .NET dissembler. I use IL Dasm which comes with a Visual Studio.

Dynamically Creating a New .NET Assembly

Classes we need to examine are:

  • AppDomain – controls isolated environment where our assemblies are running
  • AssemblyName – allows us to identify our assembly
  • AssemblyBuilder – key class for creating a new assembly dinamically
  • ModuleBuilder, TypeBuilder, MethodBuilder – additional classes used to define methods, types, etc
  • ILGenerator – class which generates .NET IL code for us

Code:

using System.Reflection;
using System.Reflection.Emit;
private static void GenerateNewAssembly(string name, string fileName)
{
    // get an instance to our isolated environment, aka ApplicationDomain
    AppDomain appDomain = AppDomain.CurrentDomain;

    // create a descriptor for our new assembly and define its name
    AssemblyName assemblyName = new AssemblyName(name);

    // define AssemblyBuilder and assign its rights
    AssemblyBuilder aBuilder = appDomain.DefineDynamicAssembly(assemblyName,
        AssemblyBuilderAccess.Save);    // AssemblyBuilder can only save our new assembly

    // creating assembly's core module specifying name and file name (location)
    ModuleBuilder mBuilder = aBuilder.DefineDynamicModule(name, fileName);

    // define a Type that we'll use
    TypeBuilder tBuilder = mBuilder.DefineType(name + "Type", TypeAttributes.Public);

    // and finally let's define our first method - Main() (which is required for any executable file)
    MethodBuilder methodBuilder = tBuilder.DefineMethod("Main",
        MethodAttributes.Public | MethodAttributes.Static,  // method attributes == public static void Main() {}
        null, null);

    // declare that your Main function will be an entry point for our assembly
    aBuilder.SetEntryPoint(methodBuilder,
        PEFileKinds.ConsoleApplication); // we will set a target to CUI rather than GUI for this example

    // IL code generator for our Main method
    ILGenerator il = methodBuilder.GetILGenerator();
    // create our IL code
    CreateIL(il);

    // create our defined Type
    tBuilder.CreateType();

    // save our new assembly
    aBuilder.Save(fileName);
}

private static void CreateIL(ILGenerator il)
{
    // System.Console.WriteLine("Hello World!"); translated to IL code with ILGenerator help
    il.EmitWriteLine("Hello World!");
    // end Main method with a return call
    il.Emit(OpCodes.Ret);
}

Adding IL Code

Now we can call GenerateNewAssembly(“Test”, “test.exe”) method to generate a new Test assembly in “test.exe” file. The new executable file can be used as any other .NET .exe assembly, but all it does – displays a simple “Hello World!” text and quits. What if we want to add some functionality? Let’s say, add Console.ReadKey() method to wait for user’s input before closing. Time to expand our CreateIL() method and dive into IL code.

First, we need to figure out what IL operation codes we need to use to call Console.ReadKey() method. Let’s create a simple console application that has only a Console.ReadKey() in it. Compile. Run Visual Studio Command Prompt and start IL Dasm (execute “ildasm” command in the command prompt). Open the assembly and check IL code.

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       8 (0x8)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
  IL_0006:  pop
  IL_0007:  ret
} // end of method Program::Main
  • Line 8 – nop operation that does absolutely nothing. Just skips the CPU cycle (mainly used to reduce overhead).
  • Line 9 – call operation with provided argument to specific method.
  • Line 10 – pop operation, which “pops” last entry in the assembly allocated stack. Stack is a place where methods pass their results, and since ReadKey() method returns us ConsoleKeyInfo object, we need to retrieve (“pop”) it from the stack, even if we won’t use it.
  • Line 11 – ret operation equivalent to return call, which ends our method’s execution.

So, let’s extend our CreateIL() method to incorporate this IL.

private static void CreateIL(ILGenerator il)
{
    // System.Console.WriteLine("Hello World!"); translated to IL code with ILGenerator help
    il.EmitWriteLine("Hello World!");

    // get ReadKey() method information
    // GetMethod() will searh for specified method in .NET
    MethodInfo mInfo = typeof(System.Console).GetMethod("ReadKey",
        Type.EmptyTypes);       // we're not passing any parameters therefore Type.EmptyTypes
        // if we're looking for a method with additional parameters, you would need to specify their type
        // ...new Type[] { typeof(..), .. }
        // i.e. WriteLine("Hello") would be:
        // MethodInfo mInfo = typeof(System.Console).GetMethod("WriteLine", new Type[] { typeof(String) });

    // write "call" OP code with ReadKey method's information
    il.Emit(OpCodes.Call, mInfo);

    // pop the stack - retrieving the result
    il.Emit(OpCodes.Pop);

    // end Main method with a return call
    il.Emit(OpCodes.Ret);
}

Conclusion

There you have it. By using ILDasm, you can easily explore all OP Codes for any .NET assembly and then using System.Reflection classes recreate it dynamically. Analyzing our newly created test.exe with ILDasm, we can see that our IL looks exactly the same as we originally wanted.
ILDASM

You can explore DeleteAfterRunning sources for more examples of Emit class usage.

DeleteAfterRunning

Feb 9, 2011   //   by Ramas   //   Project, Software  //  No Comments

Small open source application allowing you to convert any file to self-deleting executable file. You have a picture, audio file or a document you want to share, but don’t want anyone to keep a copy? Simply create a self-deleting package using DeleteAfterRunning that can be opened once, and when the user finished viewing the file, it will automatically destroys itself, preventing making a copy.
DeleteAfterRunning

Here’s how it works:

  1. You select a file from your computer. Can be any file – picture, document, video, you name it.
  2. Use DeleteAfterRunning to create an executable (*.exe) file.
  3. Share your file.
  4. Once a user opens the file, it will run as any ordinary file.
  5. After a user closes the file, it will automatically securely deletes itself preventing making any copies or running it again.

Software is open-source (released under MIT license), fast and lightweight. No installation needed. Just download and run. Currently in Beta development stage. You can grab the latest copy from Codeplex.

Hey There!

Ramunas Geciauskas

  Hey, I'm Ramas. I'm a Software Engineer, focusing on converting complex and unusual ideas into reality. I mainly work as a freelance developer, creating various web start-ups or unique software applications.

  On my spare time, I enjoy photography, admire art, and read all kinds of scientific papers.