Click here to Skip to main content
15,881,172 members
Articles / Programming Languages / C#
Article

Post build step static linking tool for C#, using ILMerge

Rate me:
Please Sign up or sign in to vote.
4.62/5 (12 votes)
1 Dec 20052 min read 80.8K   763   30   11
Post build step static linking tool for C#, using ILMerge.

Introduction

So there I was, wanting to release an application of mine, but I didn’t want to release all the assemblies that my application used. Why? Well, that would be exporting some functionality that this particular app didn’t use, and even though it was dotfuscated, it just felt wrong.

It turns out that .NET, and even .NET 2.0, despite people asking for it, does not support static linking. For those not sure what that is – static linking is when you don’t compile to a DLL, you compile to a .lib, and then the whole thing gets linked together into one .exe file.

There are many arguments as to the pros & cons of static linking, and I am not going to get into that here – suffice to say that I wanted to static link – which is good enough for me.

So – off to Google I go, and I find that Microsoft has a tool called ILMerge, which takes a plethora of parameters. What ILMerge does is de-compile .NET assemblies and then build them all into one primary assembly. Yes, it does .NET 2.0 as well.

You can also use ILMerge within your own applications as it exposes an interface, so you can just reference it (obviously, you can only do this in VS 2005, as prior to that, you cannot use .exe files as a reference – you can however get around this in 2003 if you so wish – search CodeProject – it has been done in here!).

What HTMerge (Hollingside Technologies Merge) does is make it so simple that I just have a post build step as:

htmerge "$(TargetDir)

The “ before the $ is to ensure that directory paths with spaces in are parsed correctly. This does assume that HTMerge is on the path. Given that parameter as a post build step, all assemblies that are part of your application are merged into one .exe file, which is stored in a subdirectory called merged beneath the debug/release directory.

As it stands, this code only works properly when building a .exe type project, but the concept stands.

Hope someone finds this useful!

The code

C#
using System;
using System.Text;
using System.Collections;


namespace HTMerge
{
    class Program
    {   
        static void Main(string[] args)
        {
            try
            {
                String strDir = "";
                if (args.Length != 1)
                {
                    Console.WriteLine("Usage: HTMerge directoryName");
                    return;
                }
                else
                {
                    strDir = args[0];
                }

                String[] exeFiles = System.IO.Directory.GetFiles(strDir, "*.exe");
                String[] dllFiles = System.IO.Directory.GetFiles(strDir, "*.dll");

                ArrayList ar = new ArrayList();

                Boolean bAdded = false;

                //there might be more than 1 exe file, 
                //we go for the first one that isn't the vshost exe
                foreach (String strExe in exeFiles)
                {
                    if (!strExe.Contains("vshost"))
                    {
                        ar.Add(strExe);
                        bAdded = true;
                        break;
                    }
                }

                if (!bAdded)
                {
                    Console.WriteLine("Error: No exe could be found");
                    //I know multiple returns are bad…
                    return;
                }

                bAdded = false;

                foreach (String strDLL in dllFiles)
                {
                    ar.Add(strDLL);
                    bAdded = true;
                }

                //no point merging if nothing to merge with!
                if (!bAdded)
                {
                    Console.WriteLine("Error: No DLLs could be found");
                    //I know multiple returns are bad…
                    return;
                }


                //You will need to add a reference to ILMerge.exe from Microsoft
                //See http://research.microsoft.com/~mbarnett/ILMerge.aspx
                ILMerging.ILMerge myMerge = new ILMerging.ILMerge();

                String[] files = (String[])ar.ToArray(typeof(string));

                String strTargetDir = strDir + "\\Merged";

                try
                {
                    System.IO.Directory.CreateDirectory(strTargetDir);
                }
                catch
                {
                }

                //Here we get the first file name 
                //(which was the .exe file) and use that
                // as the output
                String strOutputFile = System.IO.Path.GetFileName(files[0]);

                myMerge.OutputFile = strTargetDir + "\\" + strOutputFile;
                myMerge.SetInputAssemblies(files);

                myMerge.Merge();
            }
            catch (Exception ex)
            {
                Console.WriteLine(String.Format("Error :{0}",ex.Message));
            }

        }
    }
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United Kingdom United Kingdom
I have been developing software since I first got hold of a ZX80 age 10. After a few years with BBC Basic and 6502 assembler (I used to write articles for PCW and Acorn User) I then discovered Pascal with Objects and quickly moved to C++ where I spent 15happy years before finding the joys of c#.

After discovering the wonders of working for myself I founded Hollingside Technologies (www.hollingside.com). We offer c# / c++ / Delphi / SQL and also management consultancy. As well as the consultancy work we have run a number of successful C# and Object Oriented Programming training courses. Past bespoke software that we have written includes mobile software (pocket PC) that integrates with MS Exchange via GPRS for a sales team; Asp.net remote hardware monitoring software; scanning and image recognition software for passport control and a heap of other stuff.

When not being a geek I play guitar in a semi-successful rock band(www.stircrazy.org) and am a competitive fencer.

Other spare time is spent walking my dogs and riding my motorbike.

After all that? Give me a good beer and a splatter movie!

Comments and Discussions

 
Bugexited with code 9009 Pin
SaurabhSavaliya23-Feb-12 21:02
SaurabhSavaliya23-Feb-12 21:02 
GeneralRe: exited with code 9009 Pin
manicguitarist23-Feb-12 22:39
manicguitarist23-Feb-12 22:39 
GeneralMy vote of 5 Pin
mungflesh9-Feb-11 4:53
mungflesh9-Feb-11 4:53 
GeneralAssemblyResolver not called Pin
John Boehm15-Jan-09 3:37
John Boehm15-Jan-09 3:37 
GeneralModification for DLL as primary assembly... Pin
manicguitarist2-Sep-08 22:19
manicguitarist2-Sep-08 22:19 
GeneralModification to Handle a DLL as the Primary Assembly Pin
Strince2-Sep-08 12:56
Strince2-Sep-08 12:56 
GeneralReferencing ILMerge.exe Pin
janreimers19-Feb-07 5:28
janreimers19-Feb-07 5:28 
Generalanother way Pin
vcepa1-Dec-05 22:50
vcepa1-Dec-05 22:50 
GeneralRe: another way Pin
margiex30-Dec-05 0:22
margiex30-Dec-05 0:22 
GeneralRe: another way Pin
vcepa30-Dec-05 2:28
vcepa30-Dec-05 2:28 
GeneralRe: another way Pin
Douba29-Jun-06 0:39
Douba29-Jun-06 0:39 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.