If your team still ships a Windows desktop app via ClickOnce, you already know the workflow: publish to a web server, let users click a .application file, and hope the prerequisites install cleanly. For years that was good enough. But modern Windows deployment has moved on. MSIX—Microsoft's containerized packaging format—promises cleaner installs, easier sideloading, and better compatibility with the Microsoft Store and enterprise management tools like Intune. The catch is that moving from ClickOnce to MSIX isn't a simple repackaging job. File associations break. Shortcuts disappear. COM registrations that worked silently under ClickOnce suddenly fail inside the MSIX container. This guide walks through the entire migration, from deciding whether to switch to debugging the inevitable first failed install.
Who Needs This Migration and What Goes Wrong Without It
Many teams assume that if ClickOnce works today, there is no reason to change. That assumption holds until one of three things happens: a new Windows security update blocks ClickOnce trust prompts, a customer demands a sideloaded .msixbundle for offline install, or you need to distribute through the Microsoft Store. ClickOnce was designed for a world where apps ran with full trust. MSIX runs inside a lightweight container with a declared capability model. Without migration, you lose the ability to serve users who expect modern deployment channels.
What typically breaks first is trust. ClickOnce relies on certificate-based ClickOnce manifests and a trust prompt that many IT departments now block via Group Policy. Users see a yellow bar saying the publisher could not be verified, and they abandon the install. MSIX uses a signed .msix file that, when properly signed with a trusted certificate, installs silently without prompts. That alone is often the trigger for migration.
Another common failure point is sideloading. ClickOnce cannot produce a single-file installer that can be copied to a USB drive or emailed. If your support team needs to install the app on a machine without internet access, you are stuck. MSIX produces a single .msix or .msixbundle file that can be double-clicked or deployed via PowerShell. Teams that skip migration end up maintaining two separate install workflows—one for online ClickOnce and one for manual ZIP extraction—which doubles the testing burden.
There is also the Windows Store requirement. If you ever plan to list your app in the Store, ClickOnce is not an option. The Store accepts only MSIX packages (or the older AppX format). Even if you have no Store plans today, the Windows UI and packaging APIs are gradually shifting to assume MSIX. Future Windows features may not support ClickOnce at all. Waiting until your app is blocked is a worse position than migrating on your own schedule.
Finally, there is the issue of file associations and protocol handlers. ClickOnce can register custom URI schemes and file extensions, but those registrations are per-user and sometimes get orphaned after uninstall. MSIX handles these declaratively in the package manifest, ensuring clean registration and removal. Teams that stay on ClickOnce often accumulate registry debris, which leads to support calls about "the old version still opening."
Prerequisites and Context to Settle First
Before you touch the packaging tools, you need to understand what MSIX changes. The most important concept is the package identity. Every MSIX package has a unique name, version, and publisher that is embedded in the manifest. This identity is used for file system and registry virtualization. Your app will see a virtualized view of the file system and registry—writes to Program Files or HKLM are redirected to a per-user, per-package location. Code that assumes it can write to arbitrary system locations will fail.
You also need a code signing certificate. MSIX packages must be signed with a certificate that chains to a trusted root. For sideloading, the certificate must be installed in the Trusted Root Certification Authorities store on each target machine. For Store distribution, Microsoft handles the signing. If you currently use a self-signed certificate for ClickOnce, you will need a proper code signing certificate—either from a public CA or from your internal PKI. Budget for this cost and the time to deploy the certificate to all client machines.
Your development environment matters. The MSIX Packaging Tool runs on Windows 10 version 1809 or later. You also need the Windows SDK, which includes the MakeAppx.exe and SignTool.exe utilities. For automated builds, you can integrate MSIX packaging into Azure DevOps or GitHub Actions using the MSIX Packaging Tool SDK. If your team uses an older build server (Windows Server 2016 or earlier), you may need to upgrade or use a separate packaging machine.
Another prerequisite is understanding your app's dependencies. ClickOnce handles prerequisites like .NET Framework or VC++ redistributables by downloading them before the app runs. MSIX can include framework dependencies as package dependencies, but the app must be able to run inside the container. If your app installs a kernel-mode driver or requires admin privileges at runtime, MSIX will not work—you will need a separate installer for that component. Many teams discover this late and have to redesign their architecture.
Finally, set up a test environment that mirrors your target machines. MSIX behaves differently on Windows 10 versus Windows 11, and on systems with different security policies. Use a clean VM for each test scenario. Do not test only on your developer machine—you will miss issues like missing VC++ runtimes or blocked script execution.
Core Workflow: Step-by-Step Conversion
The conversion process has four phases: capture, package, test, and sign. We will describe each in enough detail to get you through a first successful conversion.
Capture with the MSIX Packaging Tool
Install the MSIX Packaging Tool from the Microsoft Store or download it from the Microsoft website. Launch it and select "Application package — Create package on this machine." The tool will ask you to provide the installer (your ClickOnce .application file or the actual setup.exe). It then runs the installer while monitoring file system and registry changes. After the installation completes, you can review the captured payload and modify the package manifest. Pay special attention to the "Capabilities" tab—declare only what your app needs (internetClient, privateNetworkClientServer, etc.). Over-declaring capabilities can trigger security reviews in enterprise environments.
Edit the Manifest
The package manifest (AppxManifest.xml) is where you define file associations, protocol handlers, and start menu tiles. For a ClickOnce app, you likely had these defined in the application manifest or through custom installer code. In MSIX, they must be declared declaratively. For example, to register a .myapp file extension, add an
Test the Package
Before signing, install the package locally by double-clicking the .msix file. Check that the app launches, that file associations work, and that any COM servers your app uses are registered. If the app fails to launch, look at the Event Viewer under Applications and Services Logs > Microsoft > Windows > AppXDeployment-Server. Common errors include missing dependencies (like a specific VC++ runtime) or capability mismatches. You may need to include a .msixbundle that contains multiple architecture variants if your app targets both x86 and x64.
Sign and Deploy
Use SignTool.exe from the Windows SDK to sign the package with your code signing certificate. The command is: signtool sign /fd SHA256 /a /f MyCert.pfx /p MyPassword MyPackage.msix. After signing, verify the signature with signtool verify /pa /v MyPackage.msix. For sideloading, distribute the .msix file along with a PowerShell script that installs the certificate and the package. For enterprise deployment, you can upload the package to Intune or Configuration Manager.
Tools, Setup, and Environment Realities
Choosing the right tools depends on your team's size and automation needs. For a single developer, the MSIX Packaging Tool GUI is sufficient. For teams that package multiple apps or build daily, the command-line tools and SDK are better.
MSIX Packaging Tool vs. Command Line
The GUI tool is great for exploration: you can see exactly what files and registry keys were captured, and you can edit the manifest in a visual editor. However, it does not support scripting. For automated builds, use MakeAppx.exe to create the package from a folder of files, and SignTool.exe to sign. You can also use the MSIX Packaging Tool SDK to integrate packaging into a CI pipeline. Many teams start with the GUI for the first conversion, then script the process for subsequent releases.
Handling Framework Dependencies
MSIX supports framework packages—for example, the .NET Runtime can be declared as a dependency. Your package will not install unless the required framework is present. This is cleaner than ClickOnce's prerequisite download, but it means your users must have the correct framework version installed. For .NET Framework apps, you can include the framework as a package dependency or bundle it inside the package (though that increases size). For .NET Core/5+ apps, use the Windows Desktop Runtime framework package.
Environment Differences
Windows 10 and Windows 11 handle MSIX slightly differently. On Windows 10, sideloading requires enabling the "Sideload apps" setting in Settings > Update & Security > For developers. On Windows 11, sideloading is enabled by default for domain-joined machines, but home editions may still need the setting turned on. Also, Windows 11 introduced stricter enforcement of package identity—some apps that worked on Windows 10 may fail on Windows 11 due to missing capabilities. Always test on both OS versions if your user base includes both.
Variations for Different Constraints
Not every app can be fully converted to a pure MSIX package. Here are common scenarios and how to handle them.
App Requires Admin Privileges at Runtime
MSIX packages run with low integrity by default. If your app needs to write to the Program Files folder or modify system settings, you have two options: redesign the app to write to user-scoped locations (AppData, LocalCache), or use a separate installer for the privileged component. A common pattern is to keep the main app as an MSIX package and create a small helper service (installed via a traditional MSI) that runs with elevated privileges. The MSIX app communicates with the service via a local socket or named pipe.
ClickOnce App with COM Registration
COM servers that are registered globally (HKCR) will not work inside an MSIX container. You have two choices: convert the COM server to a side-by-side assembly (using a manifest) or move the COM registration to a separate installer. For in-process COM objects that are only used by your app, you can register them per-package using the manifest's
Hybrid Approach: ClickOnce + MSIX Sideload
If you cannot convert all users at once, you can run both deployment methods in parallel. Keep ClickOnce for existing users who are not blocked, and offer MSIX for new users or those who request sideloading. The challenge is maintaining two codebases for installation logic. One team I read about used a feature flag in the app that checked for MSIX package identity at startup; if the app was running as MSIX, it skipped the ClickOnce update check. This allowed a gradual rollout over six months.
Pitfalls, Debugging, and What to Check When It Fails
The first MSIX install almost always fails. Here are the most common issues and how to fix them.
Installation Fails with Error 0x80073CF0
This error means the package is not signed correctly or the certificate is not trusted. Verify that you used SHA256 for signing (SHA1 is not supported for MSIX). Check that the certificate is installed in the Trusted Root Certification Authorities store on the target machine. For testing, you can install the certificate manually using CertMgr.exe, but for production, deploy it via Group Policy or Intune.
App Launches but File Associations Do Not Work
If double-clicking a .myapp file opens a different program, your manifest likely has the wrong ProgID or the extension is not declared correctly. Open the AppxManifest.xml and check the
App Crashes on Startup with "Access Denied"
This usually indicates your app is trying to write to a protected location like the registry's HKLM or the file system's ProgramData. Use Process Monitor to see which path is being accessed. Then modify your app to use the package's virtualized locations: for settings, use Windows.Storage.ApplicationData.Current.LocalFolder; for temporary files, use the TEMP folder under the package's local cache. If you cannot change the app's code, you can add a registry redirection using a package extension, but that is fragile.
Frequently Asked Questions and Common Mistakes
Teams often ask whether they need to rewrite their app for MSIX. The answer is usually no—most .NET Framework and C++ desktop apps can be packaged without code changes, provided they do not rely on system-level writes. The biggest mistake is assuming the packaging tool will handle everything automatically. It captures files and registry keys, but it does not fix code that writes to system locations. You must test each feature manually.
Another common mistake is forgetting to sign the package. An unsigned .msix file will not install on any modern Windows system. Even for internal testing, sign with a test certificate. Also, do not use the same certificate for both ClickOnce and MSIX—the trust mechanisms are different. Get a dedicated code signing certificate for MSIX, preferably an EV certificate to avoid SmartScreen warnings.
Many developers also overlook the need to update their installer logic. If your app previously checked for updates via ClickOnce's automatic update mechanism, you need to replace that with a custom update checker that downloads a new .msix file and calls Add-AppxPackage via PowerShell. There are open-source libraries that handle this, or you can use the Windows Store's update mechanism if you distribute through the Store.
Finally, do not skip testing on a clean machine. Developers often test on their own systems, which already have the required runtimes and certificates. The first install on a fresh VM will reveal missing dependencies. Create a checklist: install .NET runtime, install VC++ redistributable, install certificate, then install the MSIX package. Automate this checklist in a test script.
What to Do Next: Specific Actions
If you are convinced that migration makes sense for your app, here are the concrete steps to start today.
First, pick one non-critical app—preferably a simple utility without COM registration or admin requirements—and convert it using the MSIX Packaging Tool. Do not aim for a production-ready package on the first try. Just get a signed .msix that installs and launches. This will surface any environment issues (missing SDK, certificate problems) early.
Second, set up a dedicated packaging machine or VM. Install the Windows SDK, the MSIX Packaging Tool, and your code signing certificate. Document the exact OS version and build number. This machine becomes your reference environment for all future packages.
Third, create a packaging script using MakeAppx.exe and SignTool.exe. Even if you use the GUI for the first conversion, script the process so that you can repeat it for each release. Store the script in your source control repository alongside the package manifest.
Fourth, plan your certificate deployment. If you use an internal CA, push the root certificate via Group Policy to all domain-joined machines. For external users, purchase an EV code signing certificate from a public CA. Test the certificate on a machine that has never seen it before.
Fifth, communicate the change to your users. If you are replacing ClickOnce with MSIX sideloading, provide clear instructions: download the .msix file, double-click it, and if prompted, click Install. For enterprise users, push the package via Intune or Configuration Manager. Monitor install success rates and be ready to support users who encounter trust prompts.
Finally, set a deadline for retiring the ClickOnce installer. Running two deployment methods in parallel doubles your testing and support effort. Once you have confirmed that MSIX works for 90% of your users, stop updating the ClickOnce version. Keep the old installer available for legacy systems that cannot run MSIX (Windows 10 versions before 1809), but do not invest further in it.
Comments (0)
Please sign in to post a comment.
Don't have an account? Create one
No comments yet. Be the first to comment!