Packing VB.NET Assemblies into a single Executable

I need to move onto writing a C utility today. Before I do, I need to leave myself some notes on how to do this again without the re-learning lead-time.

My boss is intimidated by deeply complex software installs, assemblies, their versions, whether they’re registered with the GAC, and the like.  In discussing what his “perfect world” number-cruncher would look like, he wanted simplicity.  I promised I’d look into finding a way of making it as simple as possibe.

What’s simpler than a single stand-alone executable file that can be run from anywhere on the target machine?  Nothing I can think of.  I began a search of the .NET terrain and found ILMerge.  The authors of ILMerge suggested that an even better, simpler approach was proposed by Jeffrey Richter, essentially making their tool redundant.

I tried ILMerge initially, reasoning that I didn’t want to pollute the codebase with deployment issues. Part of the jiggery-pokery the tool engages in has the potential to break things, esepcially around WPF.  Well the number-cruncher broke, and in odd ways, so I tried Jeffrey’s path instead.  Turns out the odd breaking wasn’t the fault of ILMerge, but I’ve fallen in love with the alternative, so that’s what I’m going with.

Jeffrey’s approach is to register a new event handler for resolving assemblies. On top of the standard approaches to assembly resolution, this new event handler will also interrogate the current assembly to see if it physically contains an assembly that it depends on.  At build-time, these “base” assemblies can be  packed into the executable assembly as “embedded resources”. This embedded resource trick is something that I recently adpoted to make unit testing with files easier to manage.

Below is an image of an embedded base assembly within the core executable assembly. I pack the release version of the base assembly, added as a link (so re-builds see the latest and greatest), and marked as an “embedded resource” to let the build process know to bury a copy of the base assembly within the executing one.

Embedding a needed Assembly within the Executable Assembly

Embedding a needed Assembly within the Executable Assembly

Jeffrey’s code is C#, and it’s using a lambda function to define the event-handler on the fly.  Unfortunately, lambda functions slow me right down when I’m trying to grok code fast, so I’ve messed with the code until it’s a more traditional approach to registering a pre-defined event-handler with the event type. Here’s the registration in VB.NET, which I place just after the main() method of the console appliction entry class:

#If CONFIG = "Release" Then
    AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf RetrieveEmbeddedAssembly
#End If

I wrap the event handler registration in an #if directive to ensure that the only time the application tries to resolve assembly retrieval fron an internal cache is for a release build of the codebase. I want debug runs to pick up and use debug assemblies. Jeffrey’s event handler is re-expressed here as a VB.NET function, tweaked to my own executing assembly references:

  Private Shared Function RetrieveEmbeddedAssembly(sender As Object, args As System.ResolveEventArgs) As System.Reflection.Assembly
    Dim resourceName As String = "EFlows." + New AssemblyName(args.Name).Name + ".dll"

    Using stream = Assembly.GetExecutingAssembly.GetManifestResourceStream(resourceName)

      Dim assemblyData = New Byte(stream.Length - 1) {}

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

      Return Assembly.Load(assemblyData)

    End Using ' stream

  End Function

And whallah. The Executable now ships with it’s base assemblies embedded in the same file. No need for install/uninstall approaches that bundle the base assemblies as distinct files. All that’s needed is to ensure that the target machine has the right .NET framework installed, and the executable can do its thing.

Advertisements

5 responses to “Packing VB.NET Assemblies into a single Executable

  1. That’s definitely nice. What to do with applications with forms? :/

    Like

  2. How about embedding more than one DLL?

    Like

    • Hi Peter.

      The link supplied above to the MWCIT project embeds two DLLs that the executable assembly relies on. There’s nothing (I’m aware of) in the code that limits the number of embedded assemblies shipped.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s