Merge Multiple .NET Assemblies Into One Using ILMerge

ILMerge is a utility for merging multiple .NET assemblies into a single .NET assembly. It works on executables and DLLs alike and comes with several options for controlling the processing and format of the output.

Today I ran into a problem merging two assemblies which targeted the .NET 4 Framework. After running the ILMerge command, I received the following exception:

An exception occurred during merging:
Unresolved assembly reference not allowed: System.Core.

I found this post by Steve Michelotti, but after implementing Steve’s solution I received this error:

Process is terminated due to StackOverflowException.

The new error led me to this post by Stephen Cleary. Not only did Stephen’s suggestion fix my particular problem, but he gives useful information on why the errors occur in the first place. Thanks, Stephen!

Go here for documentation on all ILMerge Members

The procedure below is a step-by-step listing on how you can merge two assemblies into one assembly and have that new assembly target the Microsoft .NET Framework 4

ILMerge Procedure for the .NET Framework 4
For clarity sake, the procedure below assumes that you have a Visual Studio Solution which contains two Projects with the following configurations:

  • The name of the Visual Studio Solution is ILMergeSolution
  • The names of the two projects are Project1and Project2
  • Both projects (Project1 and Project2) are configured to compile to a .DLL
  • Project1 references Project2 (i.e. When Project1 is compiled in Release mode, Project1 will output its own .DLL to its /bin/Release directory as well as the .DLL of Project2)
  • Project1 and Project2 output XML comments

ILMerge Procedure

  1. Compile/build the  the ILMergeSolution  (in Release mode), then open the \Project1\bin\Release directory
  2. Move the “Project1.dll” and “Project2.dll” and their corresponding XML files from the \Project1\bin\Release directory to the root directory of the ILMerge executable program (i.e. C:\Program Files\Microsoft\ILMerge)
  3. Open a Command Prompt (Run as Administrator)  then change the prompt directory to C:\Program Files\Microsoft\ILMerge
  4. At the prompt enter: ilmerge /out:MyMergedProjects.dll Project1.dll Project2.dll /ndebug /xmldocs /targetplatform:v4,"%ProgramFiles%\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0"
  5. The “C:\Program Files\Microsoft\ILMerge” will now contain two new files: 1. MyMergedProjects.dll and 2. MyMergedProjects.xml
  6. The MyMergedProjects.dll and MyMergedProjects.xml can now be distributed for other developers to implement in their .NET 4 application. Note: The .xml file makes it possible for consumers of the MyMergedProjects assembly to view the XML comment documentation within their Visual Studio Intellisense.

Missing the v4 .NET Framework Folder?
If you are missing the folder specified at /targetplatform:v4,"%ProgramFiles%\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0" try using this path instead /targetplatform:”v4,C:\Windows\Microsoft.NET\Framework\v4.0.30319″.

Example:
C:\Program Files (x86)\Microsoft\ILMerge>ILMerge.exe /target:winexe /targetplatform:"v4,C:\Windows\Microsoft.NET\Framework\v4.0.30319"
/out:MyMergedApp.exe MyWindowsFormApp.exe MyBusinessLogic.dll

Syntax Explained

  • c:\Program Files\Microsoft\ILMerge>: The command prompt must be at the location where the ILMerge.exe lives
  • ilmerge: This tells the command prompt to run the ILMerge.exe executable file
  • /out:MyMergedProjects.dll: The /out switch tells ILMerge to output the new assembly with a name of “MyMergedProjects.dll” and in the same directory where ILMerge.exe lives. Note: We could specify a different directory, but I think it’s easier to not have to type out a directory path here at the prompt.
  • Project1.dll: This is the name of one of the .dll’s that will be merged (Notice that we did not have to specify a path since we manually moved the .dll into the same directory that ILMerge.exe lives in.)
  • Project2.dll: This is the name of one of the .dll’s that will be merged (Notice that we did not have to specify a path since we manually moved the .dll into the same directory that ILMerge.exe lives in.)
  • /ndebug: This switch will disable the creation of a .pdb file. By default, ILMerge creates a .pdb file for the output assembly and merges into it any .pdb files found for input assemblies.
  • /xmldocs: This switch will tell ILMerge to create XML documentation for the output assembly. By default, ILMerge will NOT create XML documentation.
  • /targetplatform: This is an ILMerge method which takes two strings as its parameters and is used to explicitly set the .NET Framework version that the target assembly (MyMergedProjects.dll in this case) will use.The method signature of the /targetplatform method is /targetplatform:NetFrameworkVersion,PlatformDirectory. In its class state, the signature is public void SetTargetPlatform(string platform, string directory);.
    The MS documentation on the /targetplatform method is:

    This method sets the .NET Framework for the target assembly to be the one specified by platform. Valid strings for the first argument are “v1”, “v1.1”, “v2”, and “v4”. The “v” is case insensitive and is also optional. This way ILMerge can be used to “cross-compile”, i.e., it can run in one version of the framework and generate the target assembly so it will run under a different assembly. The second argument is the directory in which mscorlib.dll is to be found.

  • v4: The first parameter of the /targetplatform method which specifies which .NET Framework version to use.
  • “%ProgramFiles%\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0”: This is the second parameter of the /targetplatform method. It specifies the directory path of where the targeted .NET Framework version exists.
    Note the “%ProgramFiles%” entry is a standard (built-in) Windows Environment Variable which evaluates to the full path of the “Program Files” directory