73

Do you use ILMerge? Do you use ILMerge to merge multiple assemblies to ease deployment of dll's? Have you found problems with deployment/versioning in production after ILMerging assemblies together?

I'm looking for some advice in regards to using ILMerge to reduce deployment friction, if that is even possible.

ckittel
  • 6,478
  • 3
  • 41
  • 71
James Pogran
  • 4,279
  • 2
  • 31
  • 23

12 Answers12

46

I use ILMerge for almost all of my different applications. I have it integrated right into the release build process so what I end up with is one exe per application with no extra dll's.

You can't ILMerge any C++ assemblies that have native code. You also can't ILMerge any assemblies that contain XAML for WPF (at least I haven't had any success with that). It complains at runtime that the resources cannot be located.

I did write a wrapper executable for ILMerge where I pass in the startup exe name for the project I want to merge, and an output exe name, and then it reflects the dependent assemblies and calls ILMerge with the appropriate command line parameters. It is much easier now when I add new assemblies to the project, I don't have to remember to update the build script.

Dinah
  • 52,922
  • 30
  • 133
  • 149
Lamar
  • 9,769
  • 4
  • 30
  • 18
  • How did you do that release build integration? – Svish Oct 30 '09 at 08:09
  • @Svish -- http://www.hanselman.com/blog/MixingLanguagesInASingleAssemblyInVisualStudioSeamlesslyWithILMergeAndMSBuild.aspx – Sean Gough Feb 03 '10 at 16:17
  • 8
    Here's a potential workaround for ILMerge + XAML: http://richarddingwall.name/2009/05/14/wpf-how-to-combine-mutliple-assemblies-into-a-single-exe/ – scobi Aug 13 '10 at 00:04
  • http://roman.st/Article/ILMerge-and-GeneratedInternalTypeHelper - Another Workaround for ILMerge + XAML – Prat Sep 13 '13 at 13:36
  • [ILRepack](https://github.com/gluck/il-repack) is an open source alternative, and (to some extend) supports WPF repacking. – Gluck Jan 30 '14 at 19:57
  • 2
    @Lamar Could you share that wrapper .exe for ILMerge? – florien Sep 19 '17 at 05:51
43

Introduction

This post shows how to replace all .exe + .dll files with a single combined .exe. It also keeps the debugging .pdb file intact.

For Console Apps

Here is the basic Post Build String for Visual Studio 2010 SP1, using .NET 4.0. I am building a console .exe with all of the sub-.dll files included in it.

"$(SolutionDir)ILMerge\ILMerge.exe" /out:"$(TargetDir)$(TargetName).all.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll" /target:exe /targetplatform:v4,C:\Windows\Microsoft.NET\Framework64\v4.0.30319 /wildcards

Basic hints

  • The output is a file "AssemblyName.all.exe" which combines all sub-dlls into one .exe.
  • Notice the ILMerge\ directory. You need to either copy the ILMerge utility into your solution directory (so you can distribute the source without having to worry about documenting the install of ILMerge), or change the this path to point to where ILMerge.exe resides.

Advanced hints

If you have problems with it not working, turn on Output, and select Show output from: Build. Check the exact command that Visual Studio actually generated, and check for errors.

Sample Build Script

This script replaces all .exe + .dll files with a single combined .exe. It also keeps the debugging .pdb file intact.

To use, paste this into your Post Build step, under the Build Events tab in a C# project, and make sure you adjust the path in the first line to point to ILMerge.exe:

rem Create a single .exe that combines the root .exe and all subassemblies.
"$(SolutionDir)ILMerge\ILMerge.exe" /out:"$(TargetDir)$(TargetName).all.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll" /target:exe /targetplatform:v4,C:\Windows\Microsoft.NET\Framework64\v4.0.30319 /wildcards
rem Remove all subassemblies.
del *.dll
rem Remove all .pdb files (except the new, combined pdb we just created).
ren "$(TargetDir)$(TargetName).all.pdb" "$(TargetName).all.pdb.temp"
del *.pdb
ren "$(TargetDir)$(TargetName).all.pdb.temp" "$(TargetName).all.pdb"
rem Delete the original, non-combined .exe.
del "$(TargetDir)$(TargetName).exe"
rem Rename the combined .exe and .pdb to the original project name we started with.
ren "$(TargetDir)$(TargetName).all.pdb" "$(TargetName).pdb"
ren "$(TargetDir)$(TargetName).all.exe" "$(TargetName).exe"
exit 0
Contango
  • 76,540
  • 58
  • 260
  • 305
  • 1
    See http://stackoverflow.com/questions/2961357/using-ilmerge-with-net-4-libraries – Contango Mar 20 '12 at 10:32
  • 1
    How do you show output from build? I'm having a silent problem with writing the output. http://stackoverflow.com/questions/42301103/what-should-the-typical-run-time-be-for-ilmerge – octopusgrabbus Feb 17 '17 at 15:34
  • @octopusgrabbus In Visual Studio, select `View.. Output`, select `Build`, and it shows the commandline output from the compiler (including the steps above). Alternatively, copy these commands into a `.bat` file, then run it from a DOS window to see the output. – Contango Feb 18 '17 at 16:32
10

We use ILMerge on the Microsoft application blocks - instead of 12 seperate DLL files, we have a single file that we can upload to our client areas, plus the file system structure is alot neater.

After merging the files, I had to edit the visual studio project list, remove the 12 seperate assmeblies and add the single file as a reference, otherwise it would complain that it couldnt find the specific assembly. Im not too sure how this would work on post deployment though, could be worth giving it a try.

Surgical Coder
  • 1,086
  • 1
  • 16
  • 25
7

I know this is an old question, but we not only use ILMerge to reduce the number of dependencies but also to internalise the "internal" dependencies (eg automapper, restsharp, etc) that are used by the utility. This means they are completely abstracted away, and the project using the merged utility doesn't need to know about them. This again reduces the required references in the project, and allows it to use / update its own version of the same external library if required.

Mightymuke
  • 5,094
  • 2
  • 31
  • 42
3

We had the same problem with combining WPF dependencies .... ILMerge doesn't appear to deal with these. Costura.Fody worked perfectly for us however and took about 5 minutes to get going... a very good experience.

Just install with Nuget (selecting the correct default project in the Package Manager Console). It introduces itself into the target project and the default settings worked immediately for us.

It merges the all DLLs marked "Copy Local" = true and produces a merged .EXE (alongside the standard output), which is nicely compressed in size (much less than the total output size).

The license is MIT as so you can modify/distribute as required.

https://github.com/Fody/Costura/

rexall
  • 101
  • 1
  • 4
3

Note that for windows GUI programs (eg WinForms) you'll want to use the /target:winexe switch.
The /target:exe switch creates a merged console application.

dlchambers
  • 3,511
  • 3
  • 29
  • 34
3

We use ILMerge on quite a few projects. The Web Service Software Factory, for example produces something like 8 assemblies as its output. We merge all of those DLLs into a single DLL so that the service host will only have to reference one DLL.

It makes life somewhat easier, but it's not a big deal either.

Esteban Araya
  • 29,284
  • 24
  • 107
  • 141
2

I'm just starting out using ILMerge as part of my CI build to combine a lot of finely grained WCF contracts into a single library. It works very well, however the new merged lib can't easily co-exist with its component libraries, or other libs that depend on those component libraries.

If, in a new project, you reference both your ILMerged lib and also a legacy library that depends on one of the inputs you gave to ILMerge, you'll find that you can't pass any type from the ILMerged lib to any method in the legacy library without doing some sort of type mapping (e.g. automapper or manual mapping). This is because once everything's compiled, the types are effectively qualified with an assembly name.

The names will also collide but you can fix that using extern alias.

My advice would be to avoid including in your merged assembly any publicly available lib that your merged assembly exposes (e.g. via a return type, method/constructor parameter, field, property, generic...) unless you know for sure that the user of your merged assembly does not and will never depend on the free-standing version of the same library.

Steve Pick
  • 186
  • 1
  • 5
1

We ran into problems when merging DLLs that have resources in the same namespace. In the merging process one of the resource namespaces was renamed and thus the resources couldn't be located. Maybe we're just doing something wrong there, still investigating the issue.

Patrick
  • 1,328
  • 10
  • 19
0

We just started using ILMerge in our solutions that are redistributed and used in our other projects and so far so good. Everything seems to work okay. We even obfuscated the packaged assembly directly.

We are considering doing the same with the MS Enterprise Library assemblies.

The only real issue I see with it is versioning of individual assemblies from the package.

markom
  • 2,040
  • 1
  • 21
  • 29
0

I recently had issue where I had ilmerged assembly in the assembly i had some classes these were being called via reflection in Umbraco opensource CMS.

The information to make the call via reflection was taken from db table that had assembly name and namespace of class that implemented and interface. The issue was that the reflection call would fail when dll was il merged however if dll was separate it all worked fine. I think issue may be similar to the one longeasy is having?

Ismail
  • 1
-2

It seems to me like the #1 ILMerge Best Practice is Don't Use ILMerge. Instead, use SmartAssembly. One reason for this is that the #2 ILMerge Best Practice is to always run PEVerify after you do an ILMerge, because ILMerge does not guarantee it will correctly merge assemblies into a valid executable.

Other ILMerge disadvantages:

  • when merging, it strips XML Comments (if I cared about this, I would use an obfuscation tool)
  • it doesn't correctly handle creating a corresponding .pdb file

Another tool worth paying attention to is Mono.Cecil and the Mono.Linker [2] tool.

[2]: http:// www.mono-project.com/Linker

user429921
  • 309
  • 1
  • 10
  • "it doesn't correctly handle creating a corresponding .pdb file" - under what conditions is this true? I've watched ILMerge generate merged pdb's, and used them without issue. – scobi Aug 25 '10 at 16:18
  • When any of the assemblies you want to merge does not already have a .pdb. Also, SmartAssembly correctly handles WPF resources such as BAML. – user429921 Aug 25 '10 at 23:26
  • A big advantage ILMerge has over Smartassembly, is that it will merge XML documentation files. Smartassembly will not do this as of the date of posting. - A paid Smartassembly user – Cameron Mar 19 '15 at 01:31