ClickOnce for Rust Apps

Taggart Software LLC
4 min readDec 25, 2020

--

ClickOnce is a cool decentralized way of distributing applications on Windows. I’ll demonstrate distributing a Rust language application using ClickOnce. The game uses Rust/WinRT to build a UI on top of the Windows Runtime. ClickOnce shipped with .NET Framework 2.0 in January of 2006. Almost 15 years later, .NET 5.0 was announced with improved ClickOnce support. A simple .NET 5.0 app is used to launch the bundled game.

Published to GitHub Pages

I published the app to GitHub Pages in an orphaned gh-pages branch. A concern of this approach may be bloat for the GitHub repository. One way to keep the repository smaller is to not keep history in that branch by force pushing to it. I published the Minesweeper.application file and the entire Application Files/Minesweeper_0_1_0_0 folder.

The Application Files folder contains all the files with a .deploy extension. To avoid some checksum validation problems due to different line endings, I added a .gitattributes file.

The published files were copies from the ClickOnce the app.publish folder. The ClickOnce can be tested locally by double clicking on the Minesweeper.application. The .NET launcher can be tested without ClickOnce by just clicking on the Minesweeper.exe. The Rust app can be tested without the .NET launcher by clicking on the minesweeper-rs.exe.

ClickOnce Publishing

I put all the files needed to publish via ClickOnce in a folder named ClickOnce. After building the Rust app with cargo build --release, I just call .\ClickOnce\build.ps1. It launches msbuild to build the .NET launcher, create the ClickOnce Application Manifest, create the ClickOnce Deployment Manifest, and sign both of them, creating the app.publish folder above. The targets come with any version of Visual Studio, include Visual Studio Build Tools. The targets to sign the manifests do not work with dotnet msbuild yet, so stick to msbuild. In PowerShell, I can add add it to the PATH environment variable with $env:PATH

FYI, Visual Studio Build Tools are available using winget. Run winget install Microsoft.VisualStudio.BuildTools. There are a few ways to install winget, but I usually just download and launch the latest .appxbundle from the most recent release on the releases page. Running the Visual Studio Installer app will help you update if you wish to.

You could build the ClickOnce manifests by hand, but it is much easier to let the MSBuild targets do it for you using a publish profile. A publish profile is itself an MSBuild file containing a bunch of properties and items.

The ClickOnce\Properties\PublishProfiles\ClickOnceProfile.pubxml was generated from a Build > Publish wizard in Visual Studio. I’m not sure what the minimal set of properties are.

I moved a couple of the properties into a ClickOnceProfile.pubxml.user file that are specific to a particular user and shouldn’t be committed. The InstallUrl is the base URL for the deployments. The ManifestCertificateThumbprint is the certificate of my locally installed code signing certificate.

.NET Launcher

The .NET app that starts the Rust app is a very basic Windows Form application.

The project file is also straight forward, but take the time to read how .NET 5.0 has changed things, especially TargetFramework:

Windows desktop APIs (including Windows Forms, WPF, and WinRT) will only be available when targeting net5.0-windows. You can specify an operating system version, like net5.0-windows7 or net5.0-windows10.0.17763.0 ( for Windows October 2018 Update). You need to target a Windows 10 version if you want to use WinRT APIs.

I added the Configuration and PublishProfile properties to that project file, but you leave them out and pass them in or override them by passing them as parameters to msbuild on the command line, such as /p:Configuration=Release and /p:PublishProfile=ClickOnceProfile.

Wrapping it Up

I enjoy seeing Rust being used more for desktop application development. Projects like Rust/WinRT and gtk-rs are making desktop application development more accessible from Rust. I’m looking forward to even better support for WinUI 3 and GTK 4.0. Even though ClickOnce is a .NET component, it can be used to distribute desktop apps built in Rust as well.

--

--

No responses yet