I'm testing out ILMerge for a new project, and although the .exe file seems to be created correctly, it won't run.
I have installed ILMerge via the .msi installer (found here http://www.microsoft.com/download/en/confirmation.aspx?id=17630) and am running on a test project using a batch file. Below is the batch file, and the subsequent output log after running. All appears ok in the logs, no errors reported. I am running .NET framework 4.0 for this test project.
When I try to run the .exe, it fails with a standard "This program has stopped working".
I have read that some people have issues running with .NET 4, but I think I've added in the correct arguments to handle this. I get the same result whether I add in the .NET 4 args or not.
Can anyone see why this may be? Thanks in advance.
Batch file
REM Clear directory first
CD C:\WORKING\DIR\TestILMerge\TestILMerge\bin\Debug\CombinedDLL
DEL . /s/q
REM Change dir to iLMerge install (installed via msi installer)
REM Installer Download: http://www.microsoft.com/download/en/confirmation.aspx?id=17630
CD C:\Program Files (x86)\Microsoft\ILMerge\
REM Combine assemblies with logging
ilmerge.exe /lib:"C:\Windows\Microsoft.NET\Framework\v4.0.30319" /lib:"C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies" /t:exe /log:C:\WORKING\DIR\TestILMerge\TestILMerge\bin\Debug\CombinedDLL\MergeLog.txt /target:winexe /targetplatform:v4,C:\Windows\Microsoft.NET\Framework\v4.0.30319 /out:C:\WORKING\DIR\TestILMerge\TestILMerge\bin\Debug\CombinedDLL\CombinedDLL.exe C:\WORKING\DIR\TestILMerge\TestILMerge\bin\Debug\TestILMerge.exe C:\WORKING\DIR\TestILMerge\TestDLL2\bin\Debug\TestDLL2.dll C:\WORKING\DIR\TestILMerge\TestDLL3\bin\Debug\TestDLL3.dll
Log output:
ILMerge version 2.11.1103.0
Copyright (C) Microsoft Corporation 2004-2006. All rights reserved.
ILMerge /lib:C:\Windows\Microsoft.NET\Framework\v4.0.30319 /lib:C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies /t:exe /log:C:\WORKING\DIR\TestILMerge\TestILMerge\bin\Debug\CombinedDLL\MergeLog.txt /target:winexe /targetplatform:v4,C:\Windows\Microsoft.NET\Framework\v4.0.30319 /out:C:\WORKING\DIR\TestILMerge\TestILMerge\bin\Debug\CombinedDLL\CombinedDLL.exe C:\WORKING\DIR\TestILMerge\TestILMerge\bin\Debug\TestILMerge.exe C:\WORKING\DIR\TestILMerge\TestDLL2\bin\Debug\TestDLL2.dll C:\WORKING\DIR\TestILMerge\TestDLL3\bin\Debug\TestDLL3.dll
Set platform to 'v4', using directory 'C:\Windows\Microsoft.NET\Framework\v4.0.30319' for mscorlib.dll
Running on Microsoft (R) .NET Framework v2.0.50727
mscorlib.dll version = 2.0.0.0
The list of input assemblies is:
C:\WORKING\DIR\TestILMerge\TestILMerge\bin\Debug\TestILMerge.exe
C:\WORKING\DIR\TestILMerge\TestDLL2\bin\Debug\TestDLL2.dll
C:\WORKING\DIR\TestILMerge\TestDLL3\bin\Debug\TestDLL3.dll
Trying to read assembly from the file 'C:\WORKING\DIR\TestILMerge\TestILMerge\bin\Debug\TestILMerge.exe'.
Successfully read in assembly.
There were no errors reported in TestILMerge's metadata.
Trying to read assembly from the file 'C:\WORKING\DIR\TestILMerge\TestDLL2\bin\Debug\TestDLL2.dll'.
Successfully read in assembly.
There were no errors reported in TestDLL2's metadata.
Trying to read assembly from the file 'C:\WORKING\DIR\TestILMerge\TestDLL3\bin\Debug\TestDLL3.dll'.
Successfully read in assembly.
There were no errors reported in TestDLL3's metadata.
Checking to see that all of the input assemblies have a compatible PeKind.
TestILMerge.PeKind = ILonly, Requires32bits
TestDLL2.PeKind = ILonly
TestDLL3.PeKind = ILonly
All input assemblies have a compatible PeKind value.
Using assembly 'TestILMerge' for assembly-level attributes for the target assembly.
Merging assembly 'TestILMerge' into target assembly.
Merging assembly 'TestDLL2' into target assembly.
Merging assembly 'TestDLL3' into target assembly.
Copying 2 Win32 Resources from assembly 'TestILMerge' into target assembly.
Transferring entry point 'TestILMerge.Program.Main(System.String[])' from assembly 'TestILMerge' to assembly 'CombinedDLL'.
There were no errors reported in the target assembly's metadata.
ILMerge: Writing target assembly 'C:\WORKING\DIR\TestILMerge\TestILMerge\bin\Debug\CombinedDLL\CombinedDLL.exe'.
Location for referenced assembly 'mscorlib' is 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll'
There were no errors reported in mscorlib's metadata.
ILMerge: Done.
UPDATE: Here is the dissassembly - looks as I would expect it to
Dissassembly
UPDATE 2
I have found that the component works if I reference from another project and use as an assembly, but not a standalone executable.
ILMerge is great if you wrote all of the assemblies that you're trying to merge, and you know that none of them are making assumptions about assembly organization. But under many circumstances (especially ones where heavy reflection or the Dynamic Language Runtime are involved), ILMerge just doesn't work. Sometimes things fail in surprising and mysterious ways.
When ILMerge fails, Jeffrey Richter has a more reliable way to get applications with multiple DLL dependencies to be deployable as a single assembly.
It isn't without trade-offs, but even the ILMerge author, Mike Barnett, said in the comment thread on that blog post "As the author of ILMerge, I think this is fantastic! If I had known about this, I never would have written ILMerge."
If you can use Richter's method, you won't trip over most of the reflection or dynamism traps.
The implementation steps
ResolveEventHandler
with the AppDomain.CurrentDomain.AssemblyResolve
event.You do part 3 as follows:
var resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name);
return Assembly.Load(new BinaryReader(resourceStream).ReadBytes(int.MaxValue));