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
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;
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");
return;
}
bAdded = false;
foreach (String strDLL in dllFiles)
{
ar.Add(strDLL);
bAdded = true;
}
if (!bAdded)
{
Console.WriteLine("Error: No DLLs could be found");
return;
}
ILMerging.ILMerge myMerge = new ILMerging.ILMerge();
String[] files = (String[])ar.ToArray(typeof(string));
String strTargetDir = strDir + "\\Merged";
try
{
System.IO.Directory.CreateDirectory(strTargetDir);
}
catch
{
}
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));
}
}
}
}