Single-File Distribution of Windows Apps - Single Binaries and the Limits of OS Dependencies
· Go Komura · Windows, Deployment, Single Binary, .NET, C++, WebView2, WinUI
This article started from the following post.
On Windows, “we’d like to ship this as a single file if possible” is a very common request. For internal tools, equipment-integration tools, monitoring terminals, offline environments, and sites that want to avoid installers as much as possible, going single-binary is very appealing.
However, if you do not untangle this conversation at the start, it usually stops making sense partway through. That is because “we want a single binary” on Windows tends to mix four separate concerns.
- We want a single distribution artifact
- We want to avoid pre-installing the .NET or Visual C++ runtimes
- We want it to run by just dropping it in place, without an installer or administrator rights
- We do not want to depend on differences between target Windows versions
These four are not the same thing. In practice, this framing keeps everyone aligned:
You can get quite far toward shipping a single EXE. But you cannot reduce the dependency on the target Windows to zero.
This article organizes that boundary for practical Windows app work.
1. The Conclusion First
Summarizing the conclusion up front:
- For an ordinary desktop EXE, you can push single-binary packaging quite far
- However, being able to ship one EXE and not depending on the target Windows are different things
- For shell extensions, Windows services, drivers, WebView2, and parts of WinUI 3, the real issue is less the file count and more what you register with the OS and what you assume about it
- The most important thing in practice is to decide separately whether you want a single binary, no installer, or fewer OS dependencies
Put another way, the lines on Windows fall like this.
- Consolidating the distribution into one artifact: quite feasible
- Bundling additional runtimes: quite feasible
- Moving toward xcopy deployment: depends on the kind of app
- Eliminating dependencies on the target Windows itself: impossible
2. Think of “Single Binary” in Four Levels
2.1 Level A: One distribution artifact
The most superficial level is this.
- You can email a single file
- You only need to put one file on a USB stick
- You only place
app.exeat the destination
This is about the apparent distribution unit. Even if the app extracts files temporarily at startup, or depends on OS-side DLLs, this condition alone can still be satisfied.
2.2 Level B: No pre-installed language runtime required
Next is the state where the app runs without pre-installing the .NET runtime or the VC++ redistributable package on the target machine.
- Static linking for C/C++
- .NET self-contained
- .NET single-file
- .NET Native AOT
At this level, the feeling of “I can carry this around on its own” gets much stronger.
2.3 Level C: No installation or registration required
From here, things suddenly get hard.
A plain EXE may run just by being dropped in place. But these are a different story.
- Shell extensions
- Windows services
- Custom URL schemes and file associations
- Drivers
- Components loaded into other processes, such as Explorer or Office
This territory is not satisfied by just placing a file. It requires registration on the OS side, or wiring into a host.
2.4 Level D: No dependency on the target Windows
This is impossible on Windows.
A Windows app ultimately runs on top of Windows APIs, the loader, the security model, and the device stack. Single-binary packaging only covers the app’s own area of responsibility. You are not taking the OS itself along with you.
3. The Areas Where a Single EXE Is Quite Achievable
Even on Windows, some apps lend themselves relatively well to a single EXE.
- Desktop tools launched standalone
- Business apps where the EXE itself owns the UI and the processing
- Tools for communication, file processing, log collection, monitoring, or equipment control
- Things that do not require host integration with Explorer or Office
- UIs that do not assume a web runtime
For this type, many things are easy to fold into the app itself.
- Your own code
- Resources
- The manifest
- Default settings
- Template data
- Some third-party libraries
- The language runtime itself
Furthermore, even without fully embedding DLLs inside the EXE, app-local deployment, placing DLLs next to the EXE, is a perfectly viable mainstream option on Windows. In practice,
- a single
app.exe - or
app.exeplus a few adjacent DLLs - with no installer, no administrator rights, distributable via xcopy
this shape is often easier to maintain than forcing everything into one EXE.
4. The Windows Dependencies That Remain Even With One EXE
If you assume “one EXE means no dependency on the target Windows,” this is where you get hurt. In reality, dependencies remain even with a single EXE.
4.1 OS version dependency
Each Windows API has a minimum supported OS. There are also x64 / Arm64 differences. So even with a single EXE, you need to pin down from the start:
- Does it run down to Windows 10?
- Is Windows 11 assumed?
- Does it also need to run on Windows Server?
- Which of x86 / x64 / Arm64 are targeted?
4.2 System DLL dependency
Even when you think you have a single EXE, at runtime you are of course using OS-provided components.
kernel32.dlluser32.dlladvapi32.dll- The COM infrastructure
- The service control infrastructure
These are Windows’ area of responsibility.
4.3 Security model dependency
- UAC
- File ACLs
- The Service Control Manager
- The registry
- Driver signing policy
Things like these cannot be absorbed into the app alone.
4.4 Host and runtime dependency
If the design is not a standalone EXE but something that rides on a host, dependencies multiply at once.
- Using WebView2: the WebView2 Runtime is needed
- Using WinUI 3 / Windows App SDK: the deployment mode needs sorting out
- Building a shell extension: registration on the Explorer side is needed
In other words, your choice of UI or integration often becomes, directly, your distribution difficulty.
5. Realistic Trade-Offs by Technology
5.1 Native C/C++
Native C/C++ sits on the high-freedom side of single-binary packaging. Static linking is an option, and a standalone EXE can be consolidated quite far.
That said, more important in practice than cramming everything into one file are:
- What to do about the UCRT and the VC++ runtime
- Whether to place third-party DLLs app-local
- How tightly to narrow the target CPU / OS
5.2 .NET
.NET offers single-file, self-contained, and Native AOT, so the apparent distribution unit can be made quite small.
But you need to keep the distinctions straight.
- framework-dependent: depends on the .NET installed in the target environment
- self-contained: carries the .NET runtime with it
- single-file: consolidates the distribution into one artifact
- Native AOT: further reduces startup-time dependencies, but comes with feature constraints
“Single-file” does not mean “fewer OS dependencies.” What it mainly reduces is how scattered the app’s distribution artifacts are.
5.3 WebView2
Adopting WebView2 completely changes the single-binary difficulty. The real subject here is not the number of EXEs but how you handle the WebView2 Runtime.
Before “can we make it one EXE,” there are questions to answer first.
- Do you assume the Runtime already exists in the environment?
- Do you use Evergreen?
- Do you bundle a Fixed Version?
- How much responsibility do you take for offline distribution?
5.4 WinUI 3 / Windows App SDK
WinUI 3 also changes your distribution requirements the moment you adopt it. Choosing the UI technology is, in itself, choosing the distribution method.
If a single binary is the top priority, it is often faster to revisit the UI technology assumption first.
6. Areas That Inherently Require Registration and Dependencies
6.1 Shell extensions
A shell extension loaded into Explorer is a different animal from a “drop-in EXE.” Here the real subject is not the file count but how you register with Explorer.
6.2 Windows services
Even if the service executable itself can be a single file, distribution is a separate problem.
- Registration with the SCM
- Privileges
- The logon account
- Recovery settings
all need consideration. In other words, services are an area where you nail down “how to install” rather than “how to make it one EXE.”
6.3 Drivers
Drivers are even more clear-cut. They only come together as a package including the INF, signing, and the installation procedure, so they barely get onto the single-binary playing field in the first place.
7. A Decision Table for Practice
For a rough judgment, this table is handy.
| What you want to build | Single-EXE feasibility | What to think about first |
|---|---|---|
| Standalone Win32 / C++ tool | High | Static linking, target OS / arch |
| Standalone WinForms / WPF tool | High | Suitability of self-contained, single-file, Native AOT |
| WinUI 3 / Windows App SDK app | Medium | Deployment mode, additional dependencies |
| WebView2-based desktop UI | Low to medium | How the Runtime is distributed |
| Explorer context-menu extension or preview handler | Low | COM / registry registration |
| Windows service | Medium | SCM registration, privileges, update procedure |
| App that bundles a driver | Low | INF, signing, installation |
The most important takeaway from this table is that “the number of binaries” and “the scope of distribution responsibility” are different things.
8. What to Decide First in Distribution Design
If you want single-binary packaging to succeed, there are things to decide before implementation.
8.1 Decide what you actually want to be “one”
- Do you want one distribution artifact?
- Do you want to eliminate runtime pre-installation?
- Do you want to eliminate the installer?
- Do you want to make offline updates easy?
The answer determines which technology you choose.
8.2 Pin down the minimum supported Windows and arch first
Both single-file and Native AOT are fundamentally OS / architecture specific. If you leave this vague and push ahead with “just make it one file,” you get stuck at the end with missing APIs or runtime mismatches.
8.3 Write down what you bundle and what you leave to Windows
In practice, just writing out this table prevents a lot of accidents.
- What the app bundles
- The main exe
- Your own DLLs
- Settings templates
- The self-contained runtime
- What you leave to Windows
- System DLLs
- OS APIs
- SCM / registry / Explorer
- The driver infrastructure
- What you assume as separate prerequisites
- WebView2 Runtime
- VC++ Redistributable
- Office / Excel
- Dedicated drivers
8.4 If you prioritize a single binary, reduce host integration
This one is quite effective.
- Drop the shell extension and make it a plain EXE
- Skip running as a service; use Task Scheduler or explicit launch instead
- Use a native UI instead of WebView2
- Keep COM closed within your own process
In short, the more you reduce designs that have the OS “load” or “register” your code, the closer you get to a single binary.
9. Summary
Single-binary packaging on Windows is feasible to a considerable extent. But it all comes down to this one statement:
You can make the app a single EXE. But you cannot make the Windows the app depends on into a single EXE.
Five points worth remembering in particular:
- For an ordinary standalone EXE, you can push single-file distribution remarkably far
- Static linking for C/C++, .NET single-file, and Native AOT are strong options
- However, dependencies on the OS version, arch, system DLLs, and the security model do not disappear
- For shell extensions, services, drivers, WebView2, and parts of WinUI 3, OS registration and additional runtimes become the main story
- Whether single-binary succeeds is decided by separating, at the start, “what exactly do we want to be one”
If you strongly prioritize a single binary, designing to lower the coupling with the OS at technology-selection time makes success far more likely.
10. References
- Microsoft Learn, Create a single file for application deployment
- Microsoft Learn, Native AOT deployment overview
- Microsoft Learn, C runtime (CRT) and C++ standard library (STL) lib files
- Microsoft Learn, Dynamic-link library search order
- Microsoft Learn, Targeting your application for Windows
- Microsoft Learn, Creating Registration-Free COM Objects
- Microsoft Learn, Registering Shell Extension Handlers
- Microsoft Learn, CreateServiceW function
- Microsoft Learn, Overview of INF Files
- Microsoft Learn, Windows driver signing tutorial
- Microsoft Learn, Distribute your app and the WebView2 Runtime
- Microsoft Learn, Windows App SDK deployment guide for self-contained apps
Related Articles
Recent articles sharing the same tags. Deepen your understanding with closely related topics.
Windows App Outsourcing and Contract Development: What to Sort Out Before You Ask
Before commissioning Windows app outsourcing or contract development, here is how to sort out existing software modification, device inte...
What Is ClickOnce? - How It Works, How It Updates, and Where It Fits (and Doesn't) in Practice
An overview of ClickOnce, the deployment technology used for .NET Windows desktop apps - manifests, updates, the cache, signing, and whic...
A Checklist for Safely Handling Child Processes in Windows Apps
Safely handling child processes in Windows apps depends less on the launch API and more on designing process tree ownership and shutdown ...
What Is MFC on Windows? Foundational Knowledge for Maintaining Existing Assets
An overview of the Microsoft Foundation Classes (MFC): its relationship to Win32, application structure, message maps, Document/View, DDX...
Handling Windows Impersonation Tokens Correctly — Borrowing Privileges per Thread and Reverting Safely
A practical guide to Windows impersonation tokens — access tokens, primary tokens, thread tokens, impersonation levels, RevertToSelf, and...
Related Topics
These topic pages place the article in a broader service and decision context.
Windows Technical Topics
Topic hub for KomuraSoft LLC's Windows development, investigation, and legacy-asset articles.
Where This Topic Connects
This article connects naturally to the following service pages.
Windows App Development
For Windows app distribution, you can avoid rework by designing single-file packaging, runtime bundling, the decision to adopt WebView2 or WinUI, and whether to run as a service, all together.
Technical Consulting & Design Review
The request 'we want a single EXE' becomes much easier to decide on once you separate the distribution unit, OS dependencies, registration requirements, and update responsibility.
Author Profile
Profile page for the article author.
Go Komura
Representative of KomuraSoft LLC
Focused on Windows software development, technical consulting, and investigations into failures that are difficult to reproduce.
Public links