Tuesday, January 15, 2013

Want to ILMerge but you're building a WPF app? Resource them baby!

The Telerik Blogs - How To: Merge assemblies into WPF application

As you may know you cannot use ILMerge to merge assemblies with XAML (WPF application) however there is a little known trick you can use to achieve your goal in a bit different way.

  • Add needed assemblies as embedded resources in your application
  • Load needed assemblies from embedded resources in runtime

How to do this?
First you need to ensure that all referenced assemblies (except the framework itself) are added properly to the application resources on every application build. To do this you can use this simple MSBuild task (AfterResolveReferences) at the end of your project:


Funny how things happen...

Last night as I was about to leave work I downloaded ILMerge. I've been wanting to use it for forever (over 8 years... that's like forever!) and finally had a real business need to do so. So I downloaded it and planned on using it this morning.

Then I caught Vladimir's above article.

Now the app I need to merge is a command line app, but still I thought the resource approach cool, so I save the article for future reference.

I started down the ILMerge path and it wasn't going so well. Getting some weird errors building the EXE, etc. I head over to the ILMerge site and guess what I see?

A Great Alternative to using ILMerge

If you cannot use ILMerge because you are trying to merge WPF assemblies, then here is a great way for you to get the same effect, courtesy of Jeffrey Richter: embed the dlls you want to merge as resources and load them on demand! In many ways, this is a better technique than using ILMerge, so I strongly urge you to check it out, even if ILMerge is working for your scenario.

Cool! So the resource approach is not only not a hack but actually "good!" And while Jeff's article is good, I thought Vladimir's even better! Almost 100% cut-n-paste and done good!

Why almost? Remember I said I was using this approach with a command line app? Well you have to be careful there.

In short, don't do the resource assembly resource/event hookup in the same block of code where you use those assemblies. The JIT will get you.

So in the Main, do the assembly stuff as shown by Vladimir's  and move your code into another routine (so your code isn't JIT'd at the same time, same block.

Once you do that, you should be good. It's worked great for me today helping me greatly streamline the deployment of one of my app's. Talk about simple xcopy deployment! :)


Related Past Post XRef:
ILMerge get's a rev...
Have a bunch of referenced DLL’s cluttering up your deployment? Just say no and ILMerge them…
Automate ILMerge'ing - Using Project Attributes to mark an Assembly for merging and then MSBuild to ILMerge them...
Gilma - GUI for ILMerge Branched for .Net 2.0
VS2005 Power Toys Pack Installer
MSBuild and ILMerge
"Gilma - GUI for ILMerge Application"
ILMerge Updated
The Code Project - Merging .NET assemblies using ILMerge - .NET

1 comment:

Markus Wehrle said...

There is a free nuget package "Costura.Fody" it packs dependency assemblies as resources into your assembly. The solution works with WPF and other managed assemblies.

If the dependency assemblies are not in the executing folder, the packed assemblies are taken automaitcally. It also configures your msbuild targets automatically for packing the dependencies during build. You do not have to add code in your assemblies. It also lets you configure, which assemblies to pack or not in a xml file.

It uses a combination of two methos:
•Jeffrey Richter's suggestion of using embedded resources as a method of merging assemblies.
•Einar Egilsson's suggestion using cecil to create module initializers.

You can find documentation here: https://github.com/Fody/Costura/blob/master/README.md