Publishing .NET Core Apps as Single-File Executables: When and How
Learn how to publish .NET Core apps as a single executable, the trade‑offs, and how to verify the result.
25 Mar 2026, 15:17 UTC

Problem: Too many files for simple deployment
When you ship a .NET Core console app to a machine that lacks the shared runtime, you end up with a folder containing the compiled DLL, the runtime, and a handful of native dependencies. Copying, versioning, or cleaning up that folder can be error‑prone, especially in restricted environments where you only have permission to drop a single file.
Thesis: Single‑file publishing gives you a self‑contained executable with minimal operational overhead
By using the dotnet publish options PublishSingleFile=true and IncludeNativeLibrariesForSelfExtract=true, the build process bundles the app, the .NET runtime, and any required native libraries into one executable. At first launch the extractor writes those native bits to a temporary folder, runs the app, and cleans up on exit.
Worked example: Creating a single‑file console app
- Open a terminal with sufficient permissions to create files and write to the temporary folder (usually a regular user account is enough).
- Create a new project:
dotnet new console -n SingleFileDemo cd SingleFileDemo - Publish a self‑contained single‑file binary for Windows x64 (adjust the RID for Linux or macOS as needed):
dotnet publish -c Release -r win-x64 ` /p:PublishSingleFile=true ` /p:IncludeNativeLibrariesForSelfExtract=true ` /p:SelfContained=trueNote: The backticks (`) are line‑continuation characters for PowerShell; in Bash replace them with a trailing backslash or place all options on one line.
- After the command finishes, inspect
bin\Release\net6.0\win-x64\publish\(the exact TFM may vary with your SDK version). You should see a single file namedSingleFileDemo.exe. - Run the executable:
You will see the console output (e.g., “Hello World!”) and, if you monitor with Process Explorer or.\SingleFileDemo.exeprocmon, a temporary folder under the user’s%TEMP%directory appears briefly while the extractor unpacks native assets.
Trade‑offs and limitations
- Startup overhead: The extractor adds a few milliseconds (typically 2‑5 ms) as it writes native binaries to disk before the runtime starts.
- Write and space requirements: The temporary extraction needs sufficient write permission and free space roughly equal to the size of the native libraries (often a few MB). In locked‑down containers or read‑only filesystems the publish will succeed but the app may fail at launch.
- Debugging experience: Some profilers and debuggers expect separate assemblies; attaching to a single‑file process may require enabling “load symbols from temporary folder” or using a framework‑dependent build instead.
- Size: The single file is larger than a framework‑dependent DLL because it contains the runtime. For very size‑sensitive scenarios you might prefer
SelfContained=falseand rely on a pre‑installed runtime.
Practical verification checklist
- Confirm the publish output contains exactly one executable (no .dll, .pdb, or .json files besides the executable).
- Run the executable on a clean machine that lacks the .NET runtime; it should start without prompting for missing DLLs.
- Use a tool such as Process Explorer to view the
DLLstab of the process while it’s running; you should see the native libraries loaded from a path under the user’s temp folder. - Check the temp folder after the process exits; the extracted files should have been removed (or at least be harmless leftovers).
Closing: When to choose single‑file publishing
If you need to drop a single executable onto a workstation, a USB stick, or a restricted server where you cannot guarantee the presence of the .NET runtime, single‑file publishing is a straightforward way to achieve a reliable, self‑contained deployment. Weigh the modest startup cost and the need for write‑able temp space against the operational simplicity of managing one file. For scenarios where the runtime is already present or where you need ultra‑fast startup, consider a framework‑dependent single‑file build (SelfContained=false) or the traditional folder‑based deployment instead.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.