Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serious trouble with ILMerge and .NET 4.0

For the life of me, I can't seem to get my .NET 4 application merging properly with ILMerge. Even after setting /targetplatform, /lib, /ndebug and adding a custom ILMerge.exe.config file the output file doesn't work properly (it doesn't seem to be able to "find" the merged libraries).

I've tried this and this to no avail. I can't even get it to build unless I use the config file, but when I do it doesn't work. Without the config file, I consistently get the error message "Unresolved assembly reference not allowed: PresentationFramework".

Here is the current state of my ILMerge command being used as a post build event:

ilmerge.exe /out:C:\Users\Logan\Development\Projects\OrangeNote\OrangeNote\bin\Release\OrangeNote.exe 
  /ndebug /targetplatform:v4,C:\Windows\Microsoft.NET\Framework\v4.0.30319 
  /lib:"C:\Windows\Microsoft.NET\Framework\v4.0.30319" 
  /lib:"C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies" 
  "C:\Users\Logan\Development\Projects\OrangeNote\OrangeNote\obj\Release\OrangeNote.exe" 
  "C:\Users\Logan\Development\Projects\OrangeNote\OrangeNote\..\..\..\Libraries\Lucene.Net\src\Lucene.Net\bin\Release\Lucene.Net.dll" 
  "C:\Users\Logan\Development\Projects\OrangeNote\OrangeNote\..\..\..\Libraries\Ookii.Dialogs\src\Ookii.Dialogs.Wpf\bin\Release\Ookii.Dialogs.Wpf.dll" 
  "C:\Users\Logan\Development\Projects\OrangeNote\OrangeNote\..\..\..\Libraries\SharpZipLib\bin\ICSharpCode.SharpZipLib.dll" 
  "C:\Users\Logan\Documents\Visual Studio 2010\Projects\HumanInterfaceProject\HumanInterfaceProject\bin\Release\HipLib.dll"

Any thoughts on what I'm doing wrong??

like image 302
devios1 Avatar asked Jul 30 '10 12:07

devios1


Video Answer


5 Answers

One suggestion I have seen used to combine .dlls in WPF is to simply add the dll as an embedded resource the the project and then programatically load the dll into the assembly.

AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => {

   String resourceName = "AssemblyLoadingAndReflection." +

      new AssemblyName(args.Name).Name + ".dll";

   using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) {

      Byte[] assemblyData = new Byte[stream.Length];

      stream.Read(assemblyData, 0, assemblyData.Length);

      return Assembly.Load(assemblyData);

   }

};

see: http://blogs.msdn.com/b/microsoft_press/archive/2010/02/03/jeffrey-richter-excerpt-2-from-clr-via-c-third-edition.aspx

like image 179
Rob Avatar answered Oct 05 '22 02:10

Rob


You could try Costura.

https://github.com/Fody/Costura#how-it-works

It basically takes Jeffrey Richters appraoch

http://blogs.msdn.com/b/microsoft_press/archive/2010/02/03/jeffrey-richter-excerpt-2-from-clr-via-c-third-edition.aspx

But does it in a way that you dont need to write any code. ie you dont need to write the "AssemblyResolve" method

like image 40
Simon Avatar answered Oct 05 '22 02:10

Simon


I emailed Mike Barnett, the author of ILMerge and he explained it's not designed to work with WPF apps at all, unfortunately, and was surprised when I told him that I had it working with my WPF 3.5 app. Since it's not really supported, I'll just write this off for now and wait for another alternative to present itself.

As a side note, I did try out .NET Reactor from Eziriz, and it actually worked great, but costs $180 which for a hobby project I'm not really willing to spend just yet. But that's a whole lot cheaper than the other commercial alternative from Red Gate and so thought I'd mention it.

Update: Mike Barnett now considers the accepted answer to this question as the best solution. According to him, if he'd known it was possible, he never would have written ILMerge in the first place.

like image 31
devios1 Avatar answered Oct 05 '22 00:10

devios1


While it is true that ILMerge does not update WPF resource strings, it can be used to merge assemblies with WPF references by passing the reference assembly directory instead of the runtime directory to /targetplatform, as such: /targetplatform:v4,"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Profile\Client" (for the .NET 4.0 client profile).

I use this to merge in Rx's System.Reactive.dll, which has a reference to Dispatcher, but doesn't have any actual WPF resources.

like image 38
Stephen Cleary Avatar answered Oct 05 '22 01:10

Stephen Cleary


I noticed that one your your assemblies is called "dialogs.wpf". Currently ILMerge does not correctly merge assemblies with WPF resources in them.

There isn't much info around on this, but this forum post mentions a possible solution, and there are several possibilities mentioned on answers to this question, but the highest voted suggestion is just to buy a commercial alternative - I don't know if that is a possibility for you.

There is a discussion here that explains why it doesn't work, and there is a suggestion here that changing the resource reference in the xaml may help solve the problem.

like image 24
Simon P Stevens Avatar answered Oct 05 '22 02:10

Simon P Stevens