I am not too familiar with .NET desktop applications (using Visual Studio 2005). Is it possible to have the entire application run from a single .exe file?
-
3Are you trying to also get rid of the need for your users to have the .Net framework installed or do you just want to link a few dlls in with the main .exe file? – Joel Coehoorn Sep 24 '08 at 13:31
12 Answers
Today, in 2015, you can use Costura.Fody for this. Using it amounts to adding the NuGet package to your project and recompiling. I'm not sure if it works with Visual Studio 2005 as in the question, but then it's not year 2008 either. I've used it in a few of my projects and it worked great.
Fody is a general purpose Code Weaver that is free and open source. The basic idea that it allows post-processing of the compiled .NET code to enhance it with features. For example, logging can be added to every method call, etc. In our case, it's packaging the dependent DLL files into the assembly resources, so that they could be loaded during the program runtime as if they were stand-alone dependencies.

- 30,738
- 21
- 105
- 131

- 25,351
- 17
- 103
- 158
-
With dotnet Core now a single exe option is available in the compiler itself so Fody developers are not maintaining it actively. – er.bhargav.vyas Aug 27 '22 at 03:07
Yes. In .NET you can have your entire application encapsulated as a single EXE file. Just make sure your solution only has one Windows Application project in it (and no other projects except for setups).
The EXE file created by your .NET project will not be a stand-alone executable file, but the only dependency it will have will be the .NET runtime (unless you add references to other DLL assemblies). If you use .NET 2.0 (which I recommend), the runtime comes preinstalled on newer PCs and is very easy and quick to set up on older machines (installer is about 23 MB).
If your app does need to reference other assemblies (like a data access DLL or a .NET class library DLL project), you could use one of the tools referenced by other posters here to combine your EXE and all referenced DLLs into a single EXE file. However, conventional practice would dictate simply deploying the EXE file along with any dependent DLLs as separate files. In .NET, deployment of dependent DLLs is pretty simple: just put them in the same folder as the EXE file on the client machine, and you're done.
It is good practice to deploy your application (whether one file or many) as a single-file installer (either a setup.EXE or setup.MSI). .NET comes with deployment project templates that can create installers for you fairly easily.
Slightly off-topic: You could use NGEN to compile your .NET application as a native EXE, but it would still be dependent upon the .NET runtime. The advantage of native compilation is that some things can be pre-compiled, but I've never seen a situation where this tiny performance increase is worth the bother.

- 74,184
- 40
- 190
- 334
-
1There is nothing in this answer that actually addresses the question, which is how to _combine_ multiple assemblies into one. – Peter Duniho Jul 20 '20 at 15:55
It's 2021 and support for this has improved by leaps and bounds.
If you've made the jump to .NET 5 (which has Windows Forms support!) you can make a single file exe that even embeds the native binaries. You must run the publish command from the command line, but it will produce a single exe with any configuration or content files along side it. The dotnet sdk does not need to exist on the target machine.
dotnet.exe publish YourProject.csproj -f net5.0 -o package/win-x64 -c Release -r win-x64 /p:PublishTrimmed=true /p:TrimMode=Link /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true
A few notes:
PublishTrimmed
can be set tofalse
to eliminate code removal in case of heavy reflection use.TrimMode
can be set tocopyused
orlink
. More details here: https://learn.microsoft.com/en-us/dotnet/core/deploying/trim-self-contained.- The
-f
parameter specifies the framework version, i.e. net5.0, etc. - The
-c
parameter is configuration, usuallyRelease
. - The
-r
parameter is the runtime to build for, can bewin-x86
,win-x64
andlinux-x64
. There may be options for ARM as well. - The
-o
parameter is the output folder.
Full reference: https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-publish

- 20,415
- 16
- 100
- 140
There is a third party tool called .NET Reactor that can do this for you. I have not used the tool and so am not sure how well it works.

- 22,580
- 14
- 83
- 137
-
1Reactor is a code-obfuscation tool. It _might_ in some cases consolidate assemblies, but that's certainly not its primary purpose, and code obfuscation has its own problems. It should _not_ be recommended as a solution to merging assemblies a la Fody, ILMerge, etc. – Peter Duniho Jul 20 '20 at 15:44
I have used the .NETZ .NET open source executable packer to pack EXE and DLL files into single EXE file. Here is a command line example for how to pack DLL files into one file:
netz -s application.exe foo.dll bar.dll

- 30,738
- 21
- 105
- 131

- 2,714
- 1
- 22
- 24
-
1
-
1also I using web service that it doesn't support. .NetZ is very good with too many options, but discontinued. – Zolfaghari Jan 16 '18 at 11:52
Jeffrey Richter wrote in his book excerpt that a callback method with the application domain’s ResolveAssembly event can be registered to enable the CLR to find third-party assemblies and DLL files during program initialization:
AppDomain.CurrentDomain.AssemblyResolve += (sender,
args) => {
String resourceName = "AssemblyLoadingAndReflection." +
new AssemblyName(args.Name).Name + ".dll";
using (var stream =
Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)){
Byte[] assemblyData = new Byte[stream.Length];
stream.Read(assemblyData, 0, assemblyData.Length);
return Assembly.Load(assemblyData);
}
};
Disclaimer: I have not used this myself. As far as I understood, the client still needs to have the .NET framework installed.

- 30,738
- 21
- 105
- 131

- 5,527
- 7
- 48
- 77
-
1This is apparently the method used by Costura.Fody which is described in the other answer: https://stackoverflow.com/a/32556235/3195477 – StayOnTarget Jan 26 '18 at 19:36
I'm using .netshrink myself, and it does exactly what you need. It packs the main and extra assemblies (DLL files) into one executable image.
I've been using it for one year already, and I'm not going back to ILMerge (it always crashes at some point...).

- 30,738
- 21
- 105
- 131

- 80
- 1
- 5
As it has been said, you can use ILMerge.
It may be easier however, if you use the free Phoenix protector, which also protects your code.

- 368
- 5
- 14
-
1Phoenix is an obfuscation tool only. The only "merging" functionality it provides is to redistribute (possibly in violation of the license) the ILMerge tool. So this answer isn't actually in any way usefully different from the answers that recommend ILMerge itself. – Peter Duniho Jul 20 '20 at 15:47
ILMerge can combine assemblies to one single assembly provided the assembly has only managed code. You can use the commandline application, or add reference to the EXE file and programmatically merge. For a GUI version, there is Eazfuscator, and also .Netz, both of which are free. Paid applications include BoxedApp and SmartAssembly.
If you have to merge assemblies with unmanaged code, I would suggest SmartAssembly. I never had hiccups with SmartAssembly, but with all others. Here, it can embed the required dependencies as resources to your main EXE file.
You can do all this manually, not needing to worry if an assembly is managed or in mixed mode by embedding the DLL file in your resources and then relying on AppDomain's Assembly ResolveHandler
. This is a one-stop solution by adopting the worst case, that is, assemblies with unmanaged code.
class Program
{
[STAThread]
static void Main()
{
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
string assemblyName = new AssemblyName(args.Name).Name;
if (assemblyName.EndsWith(".resources"))
return null;
string dllName = assemblyName + ".dll";
string dllFullPath = Path.Combine(GetMyApplicationSpecificPath(), dllName);
using (Stream s = Assembly.GetEntryAssembly().GetManifestResourceStream(typeof(Program).Namespace + ".Resources." + dllName))
{
byte[] data = new byte[stream.Length];
s.Read(data, 0, data.Length);
// Or just byte[] data = new BinaryReader(s).ReadBytes((int)s.Length);
File.WriteAllBytes(dllFullPath, data);
}
return Assembly.LoadFrom(dllFullPath);
};
}
}
Where Program
is the class name. The key here is to write the bytes to a file and load from its location. To avoid a chicken-and-egg problem, you have to ensure you declare the handler before accessing the assembly and that you do not access the assembly members (or instantiate anything that has to deal with the assembly) inside the loading (assembly resolving) part. Also take care to ensure GetMyApplicationSpecificPath()
is not any temporary directory since temporary files could be attempted to get erased by other programs or by yourself (not that it will get deleted while your program is accessing the DLL file, but at least it's a nuisance. AppData is a good location). Also note that you have to write the bytes each time; you can't load from location just because the DLL file already resides there.
For managed DLL files, you need not write bytes, but directly load from the location of the DLL file, or just read the bytes and load the assembly from memory. Like this or so:
using (Stream s = Assembly.GetEntryAssembly().GetManifestResourceStream(typeof(Program).Namespace + ".Resources." + dllName))
{
byte[] data = new byte[stream.Length];
s.Read(data, 0, data.Length);
return Assembly.Load(data);
}
// Or just
return Assembly.LoadFrom(dllFullPath); // If location is known.
If the assembly is fully unmanaged, you can see this link or this as to how to load such DLL files.
Yes, you can compress dotnet windows application into a single .exe file.
Just you have to follow the below process:
- Goto Manage NuGet Packages right clicking on your project.
- Install Costura.Fody
- Clean Debug folder inside the bin folder(Delete all files and folder).
- Run the project.
- Goto debug folder, then to app.publish folder, you will get a single exe file here.

- 704
- 8
- 9
VS2022 .net 6.0.
Use this command in a PS1 file (call the file publishSingleFile.ps1 for example):
$startFolder = $PSScriptRoot
$container = $startFolder + "/SingleFileExe"
dotnet publish --runtime win-x86 --self-contained true /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true --output $container
After that place the file in the same folder of your projectName.sln file. Right clic over the ps1 file and select "run with powershell" (if not available you must first enable powershell on your windows), that will create a folder inside your project called "SingleFileExe" with your single file there.
you can delete projectName.xml and projectName.pdb files. and you will have your projectName.exe file with everything inside.
Cheers.

- 343
- 4
- 11