1
votes

I have simple C++/CLI console application that starts another process and read it's STDOUT and STDERR. It uses external (3rd party) libraries. I'm trying to embed them into .exe image to make standalone executable for deploy.

IlMerge output:

ilmerge /log /out:test1.exe test.exe
ILMerge version 2.12.803.0
Copyright (C) Microsoft Corporation 2004-2006. All rights reserved.
ILMerge /log /out:test1.exe test.exe
Set platform to 'v2', using directory 'C:\Windows\Microsoft.NET\Framework64\v2.0.50727\..\v2.0.50727' 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:
        test.exe
Trying to read assembly from the file 'test.exe'.
        Successfully read in assembly.
        There were no errors reported in test's metadata.
Checking to see that all of the input assemblies have a compatible PeKind.
        test.PeKind = ILonly, Requires32bits
All input assemblies have a compatible PeKind value.
Using assembly 'test' for assembly-level attributes for the target assembly.
Merging assembly 'test' into target assembly.
Copying 4 Win32 Resources from assembly 'test' into target assembly.
Transferring entry point '.mainCRTStartupStrArray(System.String[])' from assembly 'test' to assembly 'test1'.
        There were no errors reported in the target assembly's metadata.
ILMerge: Writing target assembly 'test1.exe'.
AssemblyResolver: Assembly 'test' is referencing assembly 'Microsoft.VisualC'.
        AssemblyResolver: Attempting referencing assembly's directory.
        AssemblyResolver: Did not find the assembly in referencing assembly's directory.
        AssemblyResolver: Attempting input directory.
        AssemblyResolver: Did not find the assembly in the input directory.
        AssemblyResolver: Attempting user-supplied directories.
        AssemblyResolver: No user-supplied directories.
        AssemblyResolver: Attempting framework directory.
Can not find PDB file. Debug info will not be available for assembly 'Microsoft.VisualC'.
Resolved assembly reference 'Microsoft.VisualC' to 'C:\Windows\Microsoft.NET\Framework64\v2.0.50727\..\v2.0.50727\Microsoft.VisualC.dll'. (Used framework directory.)
Location for referenced module 'KERNEL32.dll' is ''
Location for referenced module 'MSVCR100.dll' is ''
Location for referenced assembly 'mscorlib' is 'C:\Windows\Microsoft.NET\Framework64\v2.0.50727\mscorlib.dll'
        There were no errors reported in mscorlib's metadata.
Location for referenced assembly 'System' is 'C:\Windows\Microsoft.NET\Framework64\v2.0.50727\system.dll'
        There were no errors reported in  System's metadata.
Location for referenced assembly 'Microsoft.VisualC' is 'C:\Windows\Microsoft.NET\Framework64\v2.0.50727\Microsoft.VisualC.dll'
        There were no errors reported in  Microsoft.VisualC's metadata.
ILMerge: Done.

One thing was little confusing me - usage of Framework64 libraries considering x86 platform of the source application.

Startup of test1.exe leads to following output in console:

Unhandled Exception: System.TypeInitializationException: The type initializer for '' threw an exception. ---> .ModuleLoadException: The C++ module failed to load during registration
 for the unload events.
 ---> System.TypeInitializationException: The type initializer for ".ModuleUninitializer" threw an exception. ---> System.MissingMethodException: Method not found: "Void System.Threading.Monitor.Enter(System.Object, Boolean ByRef)".
   in System.Runtime.CompilerServices.RuntimeHelpers.PrepareDelegate(Delegate d)
   in System.AppDomain.add_DomainUnload(EventHandler value)
   in .ModuleUninitializer..ctor() in f:\dd\vctools\crt_bld\self_x86\crt\src\minternal.h:line 255
   in .ModuleUninitializer..cctor() in f:\dd\vctools\crt_bld\self_x86\crt\src\minternal.h:line 217
   --- End of inner exception stack trace ---
   in .RegisterModuleUninitializer(EventHandler handler) in f:\dd\vctools\crt_bld\self_x86\crt\src\minternal.h:line 292
   in .LanguageSupport.InitializeUninitializer(LanguageSupport* ) in f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 426
   in .LanguageSupport._Initialize(LanguageSupport* ) in f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 545
   in .LanguageSupport.Initialize(LanguageSupport* ) in f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 697
   --- End of inner exception stack trace ---
   in .ThrowModuleLoadException(String errorMessage, Exception innerException) in f:\dd\vctools\crt_bld\self_x86\crt\src\minternal.h:line 194
   in .LanguageSupport.Initialize(LanguageSupport* ) in f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 707
   in .cctor() in f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 749
   --- End of inner exception stack trace ---

Any ideas?

2
In addition: I have same ploblems after emdedding 3rd party libraries and tried to "reassembly" only .exe image using IlMerge.Anton Novikov
Don't use ILMerge, use AppDomain.CurrentDomain.AssemblyResolve and a embedded resoruce instead. Mike Barnett, the author of ILMerge, comments on the article and says if he knew about that trick he would have never written ILMerge in the first place. Using Fody/Costura you can automate it during the build process.Scott Chamberlain
@Scott the behavior of AssemblyResolve is quite different from ILMerge (consider access to members with "internal" accessibility as just one example)Ben Voigt

2 Answers

0
votes

ILMerge can't work with C++/CLI (mixed-mode) assemblies, however the C++ linker is also capable of merging via netmodule linking.

Unlike for example the C# compiler which creates a multi-file assembly when it sees netmodules, the C++ linker will generate a single file assembly.

The output file produced by the linker will be an assembly or a .netmodule with no run-time dependency on any of the .obj or .netmodules that were input to the linker.

The trick then is to get .netmodule versions of your libraries. The DLLs ought to contain everything a .netmodule needs, but I'm not sure if any conversion tool exists. Some references indicate that ildasm+ilasm is the way to go, but this may not support conversion of assemblies which are obfuscated or mixed-mode.

0
votes

Seems solution has been found. I've taken last version 2.14.1208 of ILMerge using NuGet instead of 2.12.803 which is downloadable from Microsoft