What Is ClickOnce? - How It Works, How It Updates, and Where It Fits (and Doesn't) in Practice

· · Windows, Deployment, ClickOnce, .NET, Windows Development

When the conversation turns to distributing .NET desktop apps on Windows, one name keeps quietly coming up in the shadow of MSI and MSIX: ClickOnce.

But if you swing carelessly to either of these positions:

  • It’s old technology, so we don’t use it anymore
  • Or conversely, it looks easy, so ClickOnce can handle anything

you will usually be wrong.

ClickOnce is not an all-purpose installer that can do everything. On the other hand, for distributing internal .NET line-of-business apps to standard users, with updates included, at low operational cost, it remains a very strong option even today.

This article organizes what ClickOnce is, how it works, what it does well, and where it starts to strain — from a practical standpoint, with plenty of Mermaid diagrams. The content is primarily based on Microsoft Learn information verifiable as of April 2026.

The diagrams are conceptual. In Markdown environments with Mermaid support, they render as figures.

Table of Contents

  1. The Conclusion First
  2. What Is ClickOnce?
  3. What Makes Up ClickOnce
  4. The Flow from Install to Launch
  5. How Updates Work
  6. Where ClickOnce Excels
  7. Where It Fits
  8. Where It Doesn’t Fit
  9. Common Pitfalls in Practice
  10. Summary
  11. Related Articles
  12. References

1. The Conclusion First

In one sentence, ClickOnce is a deployment technology for distributing .NET Windows desktop apps easily on a per-user basis, with automatic updates included.

It fits cases like these.

  • Internal line-of-business apps in WinForms / WPF
  • You want standard users to be able to install
  • Per-user distribution is sufficient
  • You want updates built in
  • A website or file share is enough as the distribution channel

Conversely, with requirements like these, it is safer to look at other methods from the start.

  • Machine-wide install for all users
  • Windows services, drivers, in-process shell extensions, heavy COM registration
  • Package identity is required
  • You want to own update channels, staged delivery, and a custom rollback UX
  • The installer carries heavy responsibilities deep inside the OS

In short, ClickOnce is a method that is strong at easy distribution and easy updates, but not suited to projects with heavy OS integration.

First, the positioning in one picture

YesNoNoYesNoYesYesNoWant to distribute a Windows appAre there requirements for deep OS integration?Start from MSI / MSIXIs it a .NET Windows desktop app whereper-user distribution suffices?Do you want to distribute to standard users?Is the built-in update enough?ClickOnce is a strong candidateAlso compare xcopy / custom updater

2. What Is ClickOnce?

ClickOnce is Microsoft’s Windows app deployment technology. Officially, it is described as a deployment technology for Windows-based apps that can be installed and run with minimal user interaction and that are self-updating.

The important thing here is not to view ClickOnce as just “a kind of installer.”

In reality, ClickOnce is a deployment model that takes care of all of the following together.

  • Which version to distribute
  • Which files belong to that version
  • How to detect updates
  • Where to fetch updates from
  • How to keep the app in a safe per-user location
  • How to verify integrity at launch

The heart of ClickOnce is not setup.exe itself; it is closer to the essence to see it as a mechanism that manages distribution, updates, and cache management together, centered on manifests.

Even on current .NET, ClickOnce remains a normal candidate. In Visual Studio, the Publish tool is used for .NET Core 3.1 and .NET 5 and later, and when handling manifests manually you use dotnet-mage.exe.

The responsibilities ClickOnce takes care of

ClickOnceWhich version to distributeWhere to fetch updates fromKeep in a safe per-user locationVerify integrity and launch

3. What Makes Up ClickOnce

The shortcut to understanding how ClickOnce works is to grasp these four pieces.

Element Role
Deployment manifest (.application) Describes the version to distribute now, the update location, the update method, etc.
Application manifest (*.exe.manifest) Describes that version’s app binaries, dependent files, hashes, entry point, etc.
Application files exe, dll, config, data files, and so on
setup.exe (optional) A bootstrapper that checks for and installs prerequisites. Used when required runtimes or dependencies exist

The core here is the two kinds of manifests.

  • The deployment manifest expresses “which version is the current right answer for this app”
  • The application manifest expresses “what is inside that version”

In other words, ClickOnce’s update decision starts from the deployment manifest, and the application manifest controls what actually gets downloaded.

How the four elements relate

setup.exeoptionalcheck / install prerequisitesDeployment manifest (.application)which version to distributeupdate location / update conditionsApplication manifest (*.exe.manifest)contents of that versionfile list / hashes / entry pointApp binariesexe / dll / config / dataClickOnce cacheper-user / per-application

setup.exe is a helper, not the lead

setup.exe gets a lot of attention, but it is not the lead actor in ClickOnce. It is a helper that checks for and installs prerequisites.

For example, when the correct .NET runtime or additional redistributable components are needed, setup.exe puts those in place first, and only then does the ClickOnce deployment proper begin.

4. The Flow from Install to Launch

Boldly simplified for practical purposes, the ClickOnce flow looks like this.

  1. The user opens setup.exe or the .application file on a web page or file share
  2. In configurations using setup.exe, prerequisites are checked and any missing ones installed
  3. ClickOnce reads the deployment manifest
  4. It reads the application manifest the deployment manifest points to
  5. It fetches the required files and places them into the per-user ClickOnce cache
  6. In configurations with offline availability, it registers the app in the Start menu / app list
  7. From then on, the app launches under ClickOnce’s management

The key point is that this is not the mindset of placing files into Program Files like an ordinary installer.

ClickOnce apps go into a safe per-user cache area, isolated per app and per user. This is one of ClickOnce’s defining characteristics.

From install to first launch

App binariesClickOnce cacheApplication manifestDeployment manifestsetup.exe / .applicationUserApp binariesClickOnce cacheApplication manifestDeployment manifestsetup.exe / .applicationUserIn configurations using setup.exe,prerequisite checks come firstOpenFetch and readReference the target versionFetch required files, verify integrityPlace and launch

Online-only versus offline-available

ClickOnce offers two broad presentation modes.

  • Online-only: runs from the publish location. Feels less like a permanent install
  • Offline-available: installed onto the user’s machine and launchable from the Start menu

For internal line-of-business apps, in practice offline-available is the common choice.

Offline-availableInstalled into the user areaRegistered in the Start menuLaunches locallyChecks for updates at the configured timingOnline-onlyLaunches from the publish locationFeels less like a permanent installTends to assume a network

5. How Updates Work

ClickOnce’s most obvious strength is, after all, that the update model is built in.

Update decisions start from the deployment manifest

A ClickOnce app reads the deployment manifest and checks:

  • Is there a newer version
  • Is the update mandatory
  • Where to fetch it from

Once an update begins, ClickOnce uses file patching to avoid redundant re-downloads. As a working mental model, it is easiest to think of it as comparing the new version’s application manifest against the current version and fetching only the files that changed.

For thinking about update checks, these three patterns make it easy to organize.

  • Check before startup
  • Check after startup
  • Provide a “check for updates” UI in the app

However, the available APIs and configuration UI differ between .NET Framework and .NET 5+. Do not start implementing based only on memories of old ClickOnce articles.

The update flow

NoYesApp launchesCheck the deployment manifestIs there a newer version?Launch as isFetch the new version's application manifestCompare file signatures / hashesFetch what changedMaterialize the new version and switchIf needed, run the new version after restart

It also helps to keep in mind that, without a network connection, the app simply runs without an update check — knowing this avoids confusion in practice.

Versions are kept in isolation

ClickOnce is less “overwrite the current files in place” and more “fully materialize the new version, then switch over.”

Furthermore, the ClickOnce cache keeps the current version and the previous version separately. This is one of the reasons it rarely pollutes the environment and easily avoids version collisions.

User B's ClickOnce cachePrevious versionCurrent versionSettings / dataUser A's ClickOnce cachePrevious versionCurrent versionSettings / data

There are two key points here.

  • Hard to mix with other users
  • Hard to collide with other versions

This structure is a big part of why ClickOnce easily avoids the proverbial DLL Hell.

6. Where ClickOnce Excels

ClickOnce’s virtues go beyond “easy to distribute.” What pays off in practice is roughly this set.

6.1 Easy to distribute to standard users

ClickOnce pairs well with per-user distribution, and the big win is that it is easy to install without administrator privileges.

A common situation with internal line-of-business apps is:

  • The users are standard users
  • You do not want to file an install request with IT every time
  • But you do not want updates to stop

Under these conditions, ClickOnce is quite strong. Its premise — “install into each user’s area, safely, updates included” — matches from the start.

6.2 You do not have to implement updates yourself

Building auto-update from scratch involves more than it looks.

  • New-version detection
  • Download
  • Integrity verification
  • Switching from the old version
  • Recovery on failure
  • Update UI
  • Handling the updater itself

ClickOnce covers a large share of this with its existing model.

Responsibilities you can push onto ClickOnceNew-version detectionFetch and verifySwitchoverResponsibilities with a custom updaterNew-version detectionDownloadIntegrity verificationSwitchoverRecovery on failure

Of course, you cannot do absolutely anything you like. But the “good-enough updates” that internal apps need are quite easy to satisfy.

6.3 Apps rarely collide with each other

ClickOnce apps are isolated per app, per user, and per version.

This makes the classic accidents hard to trigger:

  • Version conflicts in shared components
  • Overwriting some DLL and breaking another app
  • Polluting the environment with manual file swaps

6.4 Easy to ship from Visual Studio

ClickOnce pairs well with Visual Studio’s publish feature, and the short distance from build to distribution is another advantage.

Before diving into a separate discipline like MSI authoring, it is easy to establish the loop of:

  • publish first
  • distribute first
  • get updates flowing first
  • get field feedback first

6.5 Settings carry-over is also relatively straightforward

If you use the default application settings provider, ClickOnce has a mechanism to merge the previous version’s settings into the new version at update time.

But note this assumes the default settings provider. With custom settings storage, custom providers, or changed storage locations, it naturally will not work as is.

7. Where It Fits

The projects ClickOnce particularly suits look roughly like these.

Situation Why it pairs well with ClickOnce
Internal WinForms / WPF line-of-business apps Standard-user distribution and auto-update mesh well
Per-user installation is sufficient Per-user distribution is natural
You want to distribute via a website or UNC share The distribution channel stays simple
Update cadence is roughly weekly to monthly The built-in update keeps up comfortably
You do not want to craft update UI as product value You can use the existing update model

Concrete examples with good practical fit:

  • Internal data-entry applications
  • Desktop business tools for quotes, ordering, inventory, and so on
  • Helper apps for configuring equipment
  • Internal-only clients distributed to branch offices, factories, and back offices
  • Apps that want updates but do not justify building a dedicated updater

For apps like these, keeping distribution and updates simple is itself the value. ClickOnce answers that value directly.

A decision tree for fit

NoYesNoYesNoYesNoYesYesNoOrganize the requirementsIs it a .NET desktop app such asWinForms / WPF?Is per-user distribution sufficient?Do you want standard users to install it?Can you distribute via web / file share?Is it OK not to over-engineer the update UX?ClickOnce is a very strong candidateCompare other methods

8. Where It Doesn’t Fit

On the other hand, the situations where you should not force ClickOnce are equally clear.

8.1 A machine-wide install is required

ClickOnce is fundamentally per-user.

  • You want to install for all users
  • You want to install under Program Files
  • You want to deploy and manage at the machine level

In these cases, MSI and friends are more natural than ClickOnce.

8.2 Windows services / drivers / shell extensions / heavy COM registration

These are matters of touching the OS deeply.

  • Windows services
  • Drivers
  • In-process shell extensions
  • Configurations that assume systematic COM registration

Once these come in, you have left ClickOnce’s “distribute lightly” worldview.

8.3 You want package identity

One reason to choose MSIX is the requirement of obtaining package identity.

ClickOnce does not go in that direction. If what you want is modern packaging or Windows features that assume package identity, prefer MSIX.

8.4 You want to own the update UX and delivery channels as product

For example:

  • stable / beta / preview channels
  • Staged delivery
  • Adjusting rollout percentages while watching telemetry
  • Fine-grained control of background downloads
  • A custom rollback strategy
  • A complex lifecycle for the updater itself

Once you want all this, ClickOnce’s built-in updates stop being enough.

8.5 Tools where “just drop it in” is enough

Conversely, some cases can be even simpler.

  • Drop in the folder and it runs
  • Manual file swaps are fine for updates
  • Hand it over on a USB stick
  • In a closed network where simplicity is the top priority

Here, xcopy distribution can involve even less friction.

Which requirements push you toward other methods

Install for all usersMSI / sometimes MSIXservice / driver / shell extension / heavy COMMSI / dedicated installerPackage identity requiredMSIXStaged delivery / channels / custom UXCustom updaterJust dropping it in is enoughxcopy

ClickOnce is not all-powerful in either direction; instead, it is a method that is strong on projects of just the right complexity.

9. Common Pitfalls in Practice

ClickOnce is convenient, but going in carelessly causes some stumbles. These in particular are worth grasping in advance.

9.1 Do not view it like “an ordinary installer”

ClickOnce is not a model where files are placed at a fixed install location in a form humans manage directly.

The actual files go into a cache managed by ClickOnce, isolated per version. That makes it a poor match for:

  • Operations that assume a fixed EXE path
  • Operations that overwrite files directly by hand
  • Operations where humans control where the actual files live

ClickOnce is not a method where people manage file placement; it is a method where the deployment state is managed by manifests.

9.2 Many old ClickOnce articles assume .NET Framework

Caution is warranted here.

Even today, search results are full of ClickOnce articles from the .NET Framework era. But on current .NET the situation differs somewhat.

  • On .NET Core 3.1 / .NET 5 / .NET 6, the ApplicationDeployment API cannot be used as is
  • On .NET 7 and later, some deployment properties can be read via environment variables
  • For manual manifest handling, dotnet-mage.exe is the assumed tool
  • On the Visual Studio side too, advice assuming the old Publish Wizard may no longer apply directly

Even if you feel you “already know ClickOnce,” it is safer not to implement from old memories.

9.3 Treat prerequisites separately

ClickOnce itself is a deployment model, but the app may need prerequisites to run.

  • A supported runtime
  • Additional redistributable components
  • Other dependencies

This is where the bootstrapper configuration using setup.exe pays off. Leave this fuzzy and you get “we distributed it with ClickOnce, but it doesn’t run.”

9.4 Settings carry-over depends on “what you store and how”

With the default settings provider, settings migration at update time is relatively straightforward. However, with:

  • A custom settings provider
  • Roaming assumptions
  • A self-managed change of the settings storage location
  • Large changes to the settings structure between versions

it naturally will not work as is.

9.5 Do not take signing and the update path lightly

ClickOnce has machinery for distribution and updates, but that does not erase your security responsibilities.

Especially in production, it is best to organize up front:

  • How the signing certificate is managed
  • How the publisher name is presented
  • How the update source is managed
  • How test self-signing is separated from production signing
verification failsCode-signing certificateApplication manifestDeployment manifestVerified on the clientUpdate / runManifest tamperingStop on verification failure

“There’s auto-update, so we’re safe” is not the conclusion; what you trust and how that trust is maintained must be considered separately.

9.6 If you move the publish location, revisit deploymentProvider

This one is unglamorous but bites hard in practice.

An installed ClickOnce app looks for updates at the location pointed to by deploymentProvider in the deployment manifest. That means even if you copy the entire publish folder to a different URL or share, without updating deploymentProvider, clients may keep looking at the original location.

And if you modify a manifest by hand, it must be re-signed.

The operational flow from publish to update pickup

BuildGenerate the new application manifestSign the application manifestUpdate the deployment manifest to the new versionSign the deployment manifestPlace at the publish locationClients detect the update

In the end, what matters in operating ClickOnce is not so much whether the files were placed as whether the manifests and signatures are consistent.

10. Summary

In one sentence, ClickOnce is

a mechanism for distributing .NET Windows desktop apps easily on a per-user basis, with updates handled at low cost.

Its strengths are mainly these.

  • Easy to distribute to standard users
  • A built-in update model
  • Easy delta-only updates
  • Easy isolation of apps and versions
  • Easy publishing from Visual Studio
  • A good match for internal line-of-business apps

But it is not all-powerful.

  • Machine-wide install
  • Services / drivers / shell extensions
  • Heavy COM registration
  • Package identity
  • Custom channels or staged delivery
  • Crafting the update UX as product value

If you have requirements like these, you should think from the MSI / MSIX / custom-updater side rather than ClickOnce.

ClickOnce is not a lightweight installer that fits everything, but on the projects it suits, it remains quite strong even today.

If what you want to distribute is

  • a .NET Windows line-of-business app,
  • where per-user installation suffices,
  • to standard users,
  • without owning updates yourself,

then ClickOnce belongs high on the candidate list.

These topic pages are close to this theme. Starting from this article, you can move on to related services and other articles.

Windows Technical Topics

An entry point that gathers technical topics on Windows development, bug investigation, and reusing existing assets.

This article connects to the following service pages. Please enter from whichever is closest.

Windows App Development

For internal line-of-business apps, equipment configuration tools, and modifications to existing software, which of ClickOnce / MSI / MSIX / xcopy has the least friction changes considerably with some organizing before implementation.

View the service Contact us

Technical Consulting & Design Review

Questions like “Is ClickOnce enough?”, “Should we lean toward MSIX or MSI?”, and “Do we settle for built-in auto-update or own it ourselves?” become much easier to decide when organized before implementation.

View the service Contact us

Author Profile

Go Komura

Representative, KomuraSoft LLC

Specializing in Windows software development, technical consulting, and bug investigation, with particular strength in projects involving existing assets and in investigating failures whose causes are hard to see.

View profile Contact us

12. References

Recent articles sharing the same tags. Deepen your understanding with closely related topics.

These topic pages place the article in a broader service and decision context.

This article connects naturally to the following service pages.

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.

Back to the Blog