Hack the Build: Use ILMerge and MSBuild to Combine Multiple Assemblies into One

Jomo Fisher--Over the last few years I've been coding mostly in C#--before that, my day-to-day work was done in C++. I don't miss much about C++, but one of the things that I do miss is the ability to link many .LIB files into a single DLL or EXE

I've known that it was possible to do this in .NET (with LINK.EXE or ILMERGE.EXE) but there is no built-ine support in VS2005 for doing this.

This weekend, I decide to see what it would take to plug ILMERGE into the regular C# build system. It's pretty simple to get basic support.

(1) Download and install ILMerge MSI: http://www.microsoft.com/downloads/details.aspx?FamilyID=22914587-b4ad-4eae-87cf-b14ae6a939b0&displaylang=en

(2) Save the this file to C:\Program Files\msbuild\Ilmerge.CSharp.targets

(3) In VS2005, right-click on the projectin solution explorer and select "Unload Project"

(4) Right-click again and pick 'Edit MyApp.csproj'

(5) Replace the <Import> line with <Import Project="$(MSBuildExtensionsPath)\Ilmerge.CSharp.targets" /> and save.

(6) Right-click again on the project in solution explorer and select "Load Project"

(7) Build.

Now, the project you modified will automatically have all referenced assemblies merged-in. Only the assemblies marked "Copy Local" will be merged so system assemblies and GAC assemblies won't be merged by default.

You only need to modify the projects you would like to have merging. In other words, you can have mixed merged and unmerged projects in the same solution.

This posting is provided "AS IS" with no warranties, and confers no rights.


Comments (15)
  1. Готовое решение. Выполняем по пунктам 1,2,3, и… Проект в Visual Studio сам соб

  2. I finished creating a code generator for Dice, and I turned the thing into a custom build task for MSBuild…

  3. margiex says:

    hi, I can build my project’s main assembly, but in vs.net when ilmerge, it reports an error: exited with code -2146232576.

    and can’t merge successfully.

    But i can merge all assembly successfully in command line.


  4. lb says:

    okay i’m starting to think that by stumbling onto your blog i’ve made my way into an alternative reality where magical things are possible.

    this is just full on. it’s one thing to describe the rough concepts behind how such a thing might be achieved… but to go ahead and produce a (supposedly) working implementation… that’s truly magical.

    okay, my brain hurts from the very thought of it.  and it’s all reminiscent of a joel spolsky article entitled ‘please sir, may i have a linker?’ which you ought to read if you haven’t, as you’ve just shown how to solve what he said was a major shortcoming of .net.



  5. Deraldo Silva says:

    Hi. After several days trying to change the csproj to do the ilmerge after build, i found this post. Thx.

    So, during my tests, although i could run the command in the cmd window, i always got errors like, "exited with code 1" or 123 or 9099 (or 9009 i dont remember).

    Using this patch to csproj, i got the "exited with code 3".

    Could you help me?

    thx in advance

  6. ASPInsiders says:

    I really like the new LINQ to XML direct language support in VB9 . However, while it’s cool, I’m not

  7. CarlH says:

    Great! But…

    In a project i use a DI-framework (Autofac) and MSTest. When i build the test lib, which references both my .exe and autofac.dll, it fails because it finds autofac classes both in the merged .exe and the .dll… If i remove the Autofac reference in the Test project it builds but the intellisens, and recognition of Autofac classes, is gone.

  8. Logan says:

    This is truly outstanding! You have no idea how giddy this makes me, to be finally able to link my assemblies together into a single cohesive unit is just… grand. I absolutely hate messy program directories with tons of scary looking files scattered about, and this lets me have a nice clean .exe file containing everything a user needs, all nicely bundled up and encapsulated.

    I do have one question if you have the time to help me; it’s not a life threatening situation or anything, but when I add a post-build call to signtool to sign my assembly with a digital signature, this occurs BEFORE the merge process, which subsequently renders the signature invalid. Is there any way I could make the post-build occur AFTER the merge?

    Thanks a lot for this, it’s really delightful and so far works like a charm.

  9. chaiguy1337 says:

    Well I managed to solve this satisfactorily by moving the code from the include file directly into the project file and being sure to place it before the post-build (signing) action. Seems to work great. Thanks again for the awesome post!

  10. Steve B. says:

    The custom target works well but the output file is no more signed (using a pfx file choose in the project properties).

    Is there anything I missed to make it working ?

  11. Simon says:

    Thanks for this valuable information!

    Is it possible to optimize the final assembly (exe) to remove code that is not used. Much like the C++ linker will discard stuff from LIBs that is not used, can ILMERGE do this for managed assemblies.

    Use case: I have several general purpose "framework" libraries I reused in a bunch of places. In most cases, I only use 5-10% of the library code. When using ILMERGE to gen a single EXE, I’d like to optimize the final EXE size by stripping all the unused objects from the resulting EXE.

  12. Proxdeveloper says:

    Great Article man, I have one question, my app has increased as for memory usage, I’m kind of sure It’s because the .exe file is loading a lot more content.

    Could you reply to to me regarding this little problem.

  13. miliu99 says:

    It would be nice if you could explain why steps 3 to 6 are necessary and what they really do. The problem is that I’m using C# express 2008, and don’t have ‘Unload Project’ menu from Solution window, so I can’t follow your steps. Are those step only necessary for an existing project? How about the new project? Why the step 5 is necessary? why can’t you put that in the script?  

  14. Ken van Riel says:

    Past this in the post-build cahnge the file name of the DLL's.


    MKDIR Merge


    "C:Program FilesMicrosoftILMergeILmerge.exe" /target:library /out:MergeWSFClient.dll Microsoft.ApplicationBlocks.Data.dll WSFClient.dll

Comments are closed.

Skip to main content