74

I have two DLL files which I'd like to include in my EXE file to make it easier to distribute it. I've read a bit here and there how to do this, even found a good thread here, and here, but it's far too complicated for me and I need real basic instructions on how to do this.

I'm using Microsoft Visual C# Express 2010, and please excuse my "low standard" question, but I feel like I'm one or two level below everyone else's expercise :-/ If someone could point out how to merge these DDL files into my EXE in a step-by-step guide, this would be really awesome!

Community
  • 1
  • 1
Momro
  • 971
  • 1
  • 10
  • 16

14 Answers14

96

For .NET Framework 4.5

ILMerge.exe /target:winexe /targetplatform:"v4,C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0" /out:finish.exe insert1.exe insert2.dll

ILMerge

  1. Open CMD and cd to your directory. Let's say: cd C:\test
  2. Insert the above code.
  3. /out:finish.exe replace finish.exe with any filename you want.
  4. Behind the /out:finish.exe you have to give the files you want to be combined.
Zombo
  • 1
  • 62
  • 391
  • 407
Yuki Kutsuya
  • 3,968
  • 11
  • 46
  • 63
  • 1
    Hurray, that worked. The problem was a "\" at the end of the directory path which was too much. – Momro Apr 13 '12 at 10:40
  • 6
    I just followed your instructions as you mention above. still not merged. please help me. In Command Prompt : `ILMerge.exe /target:winexe /targetplatform:"v4,C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0" /out:finish.exe myExe.exe mfc100u.dll mfc110u.dll msvcp110.dll` Error: `An exception occurred during merging: ILMerge.Merge: Could not load assembly from the location 'C:\test\my folder\mfc 100u.dll'. Skipping and processing rest of arguments.` Any idea whats gonin wrong ? – AB Bolim Oct 27 '13 at 07:24
  • 3
    Sometimes you have to 1) use `Program Files (x86)` 2) type the full path to ILMerge. Use `/target:exe` for console applications. – SWdV Nov 25 '17 at 22:53
  • Windows by-default comes with .NET framework here `C:\Windows\Microsoft.NET\Framework`. So you can also use `/targetplatform:"v2,C:\Windows\Microsoft.NET\Framework\v2.0.50727"` or `/targetplatform:"v4,C:\Windows\Microsoft.NET\Framework\v4.0.30319"` – Gray Programmerz Oct 07 '21 at 12:47
39

Use Costura.Fody.

You just have to install the nuget and then do a build. The final executable will be standalone.

Brett Caswell
  • 1,486
  • 1
  • 13
  • 25
Igor Popov
  • 9,795
  • 7
  • 55
  • 68
  • 1
    this is a very interesting project. but it seems to be a plugin for [Fody](https://github.com/Fody/Fody/).. so you could improve this answer a bit by providing some information on **Mono.Cecil** and **Fody** (as they are both dependencies, and are really the most relevant to the underline premise). But, yea, the plugin itself does seem to make it 'easier' to embed and distribute dlls in a configurable manner. – Brett Caswell Nov 24 '16 at 12:49
  • 6
    This is voodoo. Unbelievably easy. `Install-Package Costura.Fody` and Bam! your build will produce one big fat exe. – Cristian Diaconescu Sep 05 '17 at 16:21
  • 1
    Doesnt quite work but i support this is can happen in some cases. (Can't build and i have an error) – Antonios Tsimourtos May 19 '18 at 13:12
  • Wow - I struggled for 3 days trying to get iLMerge to work with several 3rd party dlls that had multiple other references I had to point to, and even though I had all dependencies added it still did not work and upon examining the logs it was mutating some of the namespace names, saying they were duplicate. (They were inside the 3rd party assemblies) This worked just as easy as @CristianDiaconescu said. – cmartin Jan 12 '21 at 21:04
25

Download ilmerge and ilmergre gui . makes joining the files so easy ive used these and works great

Kieran Hill
  • 267
  • 3
  • 3
18

Reference the DLL´s to your Resources and and use the AssemblyResolve-Event to return the Resource-DLL.

public partial class App : Application
{
    public App()
    {
        AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
        {

            Assembly thisAssembly = Assembly.GetExecutingAssembly();

            //Get the Name of the AssemblyFile
            var name = args.Name.Substring(0, args.Name.IndexOf(',')) + ".dll";

            //Load form Embedded Resources - This Function is not called if the Assembly is in the Application Folder
            var resources = thisAssembly.GetManifestResourceNames().Where(s => s.EndsWith(name));
            if (resources.Count() > 0)
            {
                var resourceName = resources.First();
                using (Stream stream = thisAssembly.GetManifestResourceStream(resourceName))
                {
                    if (stream == null) return null;
                    var block = new byte[stream.Length];
                    stream.Read(block, 0, block.Length);
                    return Assembly.Load(block);
                }
            }
            return null;
        };
    }
}
Destructor
  • 1,641
  • 1
  • 13
  • 13
  • 1
    Ok, I don't understand the slightest thing of what you wrote there ;-) Where do I have to put this code into? – Momro Apr 13 '12 at 09:46
  • Are you using a WPF or a WindowsForms Application? – Destructor Apr 13 '12 at 09:48
  • Ok, first you have to add the DLL´s to your project-Resources. Add a folder "Resources" to your Solution and just put your dll´s in there. Right click on your project -> Properties -> Resources. There click "Add Resource" and add your dll´s. After that go to your program.cs file and add the code to your Main() before everything else. – Destructor Apr 13 '12 at 09:51
  • 1
    For WinForms try this code instead of the code above: AppDomain.CurrentDomain.AssemblyResolve += (sender, arg) => { if (arg.Name.StartsWith("Your_DLL")) return Assembly.Load(Properties.Resources.Your_DLL); return null; }; – Destructor Apr 13 '12 at 09:57
  • Okay, I used your shortened version, but my IDE tells me that the name "Assembly" is not available in this context :-/ – Momro Apr 13 '12 at 10:13
  • Add a using System.Reflection; – Destructor Apr 13 '12 at 10:14
  • And to ensure that the referenced dll´s are not copied to the output dir, you have to select your dll´s from References and set the property "Copy Local" to false. – Destructor Apr 13 '12 at 10:23
  • So I included this code snippet for each DLL, but the EXE won't start if the DLLs aren't in the same folder (copied the EXE to desktop to test it). - And I couldn't find this property. How do I get to the *References*? If I go to the program's resources, I can't edit their properties (except for Comment, Filename, FileType, Persistence and Type). – Momro Apr 13 '12 at 10:31
  • In your Solution Explorer there is a point "References". The Point, where you added your dll to use it in your program. There are all referenced dll listed. Select your dll and change "Copy Local" to false. – Destructor Apr 13 '12 at 10:42
  • I did that, even changing WMPLib's and AXVLC's Interop type to "false" to let me change "local copy" to false. I created a pastebin to show you the code snippet in my Program.cs: [pastebin entry](http://pastebin.com/na9GUcsS) – Momro Apr 13 '12 at 10:53
10

Download

ILMerge

Call

ilmerge /target:winexe /out:c:\output.exe c:\input.exe C:\input.dll
Zombo
  • 1
  • 62
  • 391
  • 407
  • Add: `/target:winexe /target platform:"v4,C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0"` to it if you have a .NEt framework 4.5 application :). – Yuki Kutsuya Apr 13 '12 at 09:30
  • This results in the following error message: An exception occurred during merging: Unresolved assembly reference not allowed: System.Core. - I created a bat file with the following content: `ilmerge /target:winexe my_exe.exe my_dll.dll /out:merged.exe` – Momro Apr 13 '12 at 09:40
  • @Momro Try with the target platform parameter ;). – Yuki Kutsuya Apr 13 '12 at 10:02
  • 1
    Ok, so I have this command: `ilmerge /target:winexe /target:platform:"v4,c:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\" /out:merged.exe my_exe.exe my_dll.dll`, but the prompt says that I have to specify at least one input fil and an output file. I also exchanged the out parametre with the inputs with no result. – Momro Apr 13 '12 at 10:24
9
  1. Install ILMerge as the other threads tell you to

  2. Then go to the installation folder, by default C:\Program Files (x86)\Microsoft\ILMerge

  3. Drag your Dll's and Exes to that folder

  4. Shift-Rightclick in that folder and choose open command prompt

  5. Write

    ilmerge myExe.exe Dll1.dll /out:merged.exe
    

    Note that you should write your exe first.

There you got your merged exe. This might not be the best way if your going to do this multiple times, but the simplest one for a one time use, I would recommend putting Ilmerge to your path.

Zombo
  • 1
  • 62
  • 391
  • 407
Henrik Karlsson
  • 5,559
  • 4
  • 25
  • 42
  • 1
    I just followed your instructions as you mention above. I have also put `ilmerge` to my system path. still not merged. please help me. In Command Prompt : `>ilmerge myExe.exe mfc100u.dll mfc110u.dll /out:final.exe` Error: `An exception occurred during merging: ILMerge.Merge: Could not load assembly from the location 'C:\test\my folder\mfc 100u.dll'. Skipping and processing rest of arguments.` Any idea whats gonin wrong ? – AB Bolim Oct 27 '13 at 07:03
  • Looks like your dlls name contains a space? Try putting quotes around it – Henrik Karlsson Oct 27 '13 at 08:45
  • Thanx for reply. But only in this my above comment, `mfc100u.dll` have space. I want to merge more than one `dll` file. I have also try `ILMerge GUI`. But still facing the same problem. Please help me. – AB Bolim Oct 27 '13 at 18:30
  • Could not get the above examples from other users to work, but this work perfectly. Thanks. – rerat Sep 26 '15 at 20:05
6
static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
    /* PUT THIS LINE IN YOUR CLASS PROGRAM MAIN() */           
        AppDomain.CurrentDomain.AssemblyResolve += (sender, arg) => { if (arg.Name.StartsWith("YOURDLL")) return Assembly.Load(Properties.Resources.YOURDLL); return null; }; 
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
}

First add the DLL´s to your project-Resources. Add a folder "Resources"

Paulos02
  • 163
  • 1
  • 4
6

2019 Update (just for reference):

Starting with .NET Core 3.0, this feature is supported out of the box. To take advantage of the single-file executable publishing, just add the following line to the project configuration file:

<PropertyGroup>
  <PublishSingleFile>true</PublishSingleFile>
</PropertyGroup>

Now, dotnet publish should produce a single .exe file without using any external tool.

More documentation for this feature is available at https://github.com/dotnet/designs/blob/master/accepted/single-file/design.md.

alxnull
  • 909
  • 9
  • 18
  • 1
    Nice, this works but you just need to specify `RuntimeIdentifier` or `RuntimeIdentifiers` and the file gains about 65.4 MB. – Daniel Jul 22 '20 at 23:04
2

Also you can use ilmergertool at codeplex with GUI interface.

Zain Ali
  • 15,535
  • 14
  • 95
  • 108
2

Here is the official documentation. This is also automatically downloaded at step 2.

Below is a really simple way to do it and I've successfully built my app using .NET framework 4.6.1

  1. Install ILMerge nuget package either via gui or commandline:

    Install-Package ilmerge
    
  2. Verify you have downloaded it. Now Install (not sure the command for this, but just go to your nuget packages): enter image description here Note: You probably only need to install it for one of your solutions if you have multiple

  3. Navigate to your solution folder and in the packages folder you should see 'ILMerge' with an executable:

    \FindMyiPhone-master\FindMyiPhone-master\packages\ILMerge.2.14.1208\tools
    

    enter image description here

  4. Now here is the executable which you could copy over to your \bin\Debug (or whereever your app is built) and then in commandline/powershell do something like below:

    ILMerge.exe myExecutable.exe myDll1.dll myDll2.dll myDlln.dll myNEWExecutable.exe
    

You will now have a new executable with all your libraries in one!

benscabbia
  • 17,592
  • 13
  • 51
  • 62
0

I answered a similar question for VB.NET. It shouldn't however be too hard to convert. You embedd the DLL's into your Ressource folder and on the first usage, the AppDomain.CurrentDomain.AssemblyResolve event gets fired.

If you want to reference it during development, just add a normal DLL reference to your project.

Embedd a DLL into a project

Community
  • 1
  • 1
Alex
  • 7,901
  • 1
  • 41
  • 56
0

NOTE: if you're trying to load a non-ILOnly assembly, then

Assembly.Load(block)

won't work, and an exception will be thrown: more details

I overcame this by creating a temporary file, and using

Assembly.LoadFile(dllFile)
BoJl4apa
  • 29
  • 4
0

I Found The Solution Below are the Stpes:-

  1. Download ILMerge.msi and Install it on your Machine.
  2. Open Command Prompt
  3. type cd C:\Program Files (x86)\Microsoft\ILMerge Preess Enter
  4. C:\Program Files (x86)\Microsoft\ILMerge>ILMerge.exe /target:winexe /targetplatform:"v4,C:\Windows\Microsoft.NET\Framework\v4.0.30319" /out:NewExeName.exe SourceExeName.exe DllName.dll

For Multiple Dll :-

C:\Program Files (x86)\Microsoft\ILMerge>ILMerge.exe /target:winexe /targetplatform:"v4,C:\Windows\Microsoft.NET\Framework\v4.0.30319" /out:NewExeName.exe SourceExeName.exe DllName1.dll DllName2.dll DllName3.dll

-2

The command should be the following script:

ilmerge myExe.exe Dll1.dll /target:winexe /targetplatform:"v4,c:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\" /out:merged.exe /out:merged.exe
wmk
  • 4,598
  • 1
  • 20
  • 37
Yuan
  • 1