Monday, January 30, 2012

ILMerge: Getting Started, Merging, and Alternatives (to ILMerge).

What is ILMerge?
ILMerge is a Microsoft produced assembly merge utility. It merges more-than-one .NET assembly (or executables) into a single assembly.

ILMerge is a command-line utility.

To begin you will need to install ILMerge on your machine (or the machine where you are planning on merging assemblies). You can download ILMerge directly from Microsoft in the Download center at:

The installation itself is a Microsoft Installer (MSI) file named ILMerge.msi. Click on the file, and follow the pretty typical installation path: Welcome -> License Agreement (EULA) -> Install Folder > Confirm

Note: You will want to remember the installation folder, since you will have to run ILMerge from this location (or at a minimum add this file location into the windows path). My install location was C:\Program Files (x86)\Microsoft\ILMerge

Best Practices:

  1. Script the merge process
  2. Incorporate the assembly merge into your build process

ilmerge /out:Merged.dll Primary.dll Secondary1.dll Secondary2.dll 
Merge with Wildcard:
ilmerge /wildcards /out:Merged.dll Primary.dll Secondary*.dll 
Merge with Log:
ilmerge /log /out:Merged.dll Primary.dll Secondary1.dll Secondary2.dll
ilmerge /log:log.txt /out:Merged.dll Primary.dll Secondary1.dll Secondary2.dll

IL Merge with .NET 4.0:
... when using ILMerge with .NET 4.0 assemblies you have to set the target platform to .NET 4.0 (command line parameter: /targetplatform:v4).

... Microsoft Research (via Mike Barnett) provides an example configuration file for using ILMerge with .NET 4.0 at:

This is the example:
<?xml version ="1.0"?>
<startup useLegacyV2RuntimeActivationPolicy="true">
<requiredRuntime safemode="true" imageVersion="v4.0.30319" version="v4.0.30319"/>

Are there alternatives to ILMerge (that will accomplish the same relative goal)?

Assemblies as Resources
Jeffrey Richter on the Microsoft Press blog proposed adding assemblies as resources, and loading them via reflection. You can read more about this approach here:

Using this approach, you "hook" into the assembly resolve for the AppDomain, and then load the assemblies via reflection.
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => {
   String resourceName = "AssemblyLoadingAndReflection." + new AssemblyName(args.Name).Name + ".dll";

   using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) {
      Byte[] assemblyData = new Byte[stream.Length];
      stream.Read(assemblyData, 0, assemblyData.Length);
      return Assembly.Load(assemblyData);

This blog post (Combining multiple assemblies into a single EXE for a WPF application) contains a more comprehensive approach, and includes a way to incorporate this strategy into your build process via a AfterResolveReferences target:

<Target Name="AfterResolveReferences">
    <EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'">

RedGate Smart Assembly
Smart Assembly from Red Gate's description is "an obfuscator that helps protect your .NET code against reverse-engineering, cracking, and modification".

Smart Assembly also has the ability to combine multiple assemblies into a single one.  They describe this feature as "Simplify the deployment of your application by packaging it in one file (Dependency Embedding with compression and encryption, and Dependency Merging)."

... ILMerge can not merge WPF assemblies (from a couple of sources). According to Mike Barnett the reason is "[WPF assemblies] contain resources with encoded assembly identities. ILMerge is unable to deserialize the resources, modify the assembly identities, and then re-serialize them. ". See Assemblies as Resources above for an alternative.

...  ILMerge cannot merge C++ assemblies containing native code

... Make sure you have accounted for assembly references before attempting to merge, or you will get an exception:
Missing Reference Assembly Screenshot

An exception occurred during merging:Unresolved assembly reference not allowed: System.Data.Entity.   at System.Compiler.Ir2md.GetAssemblyRefIndex(AssemblyNode assembly)   at System.Compiler.Ir2md.GetTypeRefIndex(TypeNode type)   at System.Compiler.Ir2md.VisitReferencedType(TypeNode type)   at System.Compiler.Ir2md.VisitClass(Class Class)   at System.Compiler.Ir2md.VisitModule(Module module)   at System.Compiler.Ir2md.SetupMetadataWriter(String debugSymbolsLocation)   at System.Compiler.Ir2md.WritePE(Module module, String debugSymbolsLocation,BinaryWriter writer)   at System.Compiler.Writer.WritePE(String location, Boolean writeDebugSymbols, Module module, Boolean delaySign, String keyFileName, String keyName)   at System.Compiler.Writer.WritePE(CompilerParameters compilerParameters, Module module)   at ILMerging.ILMerge.Merge()   at ILMerging.ILMerge.Main(String[] args)

... A few comments says it removes  XML Comments from the assembly.

ILMerge Download - The Microsoft download center web page that provides the download link to install ILMerge. The actual installation is ILMerge.msi.
Mike Barnett ILMerge
ILMerge config file for executing within the CLR v4.0 runtime
Jeffrey Richter: Excerpt #2 from CLR via C#, Third Edition
Combining multiple assemblies into a single EXE for a WPF application
RedGate Smart Assembly
Tools & Utilities

No comments: