Skip to content

Portable Distribution

Yasunobu edited this page Jun 26, 2026 · 1 revision

Portable Distribution

Being portable is a product requirement, and it shapes the publish settings. The goal: a folder you can copy anywhere, run without installing, and delete to remove completely — kept as small as is practical.

Publish settings (KeepPressing.csproj)

<WindowsPackageType>None</WindowsPackageType>      <!-- no MSIX registration -->
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
<SelfContained>true</SelfContained>                <!-- bundle the .NET runtime -->
<SatelliteResourceLanguages>en;ja</SatelliteResourceLanguages>
<DefaultLanguage>en-US</DefaultLanguage>

And, for non-Debug configurations:

<PublishReadyToRun>True</PublishReadyToRun>   <!-- Release: R2R for faster startup -->
<PublishTrimmed>True</PublishTrimmed>         <!-- Release: trim unused IL -->

So a Release publish is self-contained, ReadyToRun, and trimmed, with .NET satellite resources limited to English and Japanese.

The TrimPortableDistribution target

SatelliteResourceLanguages only trims .NET satellite assemblies — it doesn't touch the Windows App SDK's native MUI resources or other on-demand payloads. An MSBuild target picks up the slack after publish (AfterTargets="Publish"), so it runs on both CLI and Visual Studio publishes but not on ordinary builds. It is idempotent (a no-op on an empty set):

  1. Localized MUI folders — deletes every *.mui language folder whose name doesn't start with en or ja.
  2. PDBs — deletes *.pdb.
  3. Unused native DLLs (~44 MB) — removes WinAppSDK feature DLLs the tool never uses: ONNX/DirectML AI inference, Windows AI APIs, Graphics Imaging, Widgets, and WebView2 (onnxruntime.dll, DirectML.dll, Microsoft.Windows.AI.*.dll, Microsoft.Graphics.Imaging.dll, Microsoft.Windows.Widgets.dll, Microsoft.Web.WebView2.Core.dll, WebView2Loader.dll). These are on-demand payloads loaded only when their WinRT types are activated, so they're safe to drop. WinUIEdit / PerceptiveStreaming / CLR diagnostics are intentionally kept (used by rendering, text editing, and exception handling).

It prints a summary line, e.g.:

Trimmed portable distribution under <dir>: kept en*/ja* MUI only, removed pdb and unused SDK native DLLs (AI/Widgets/WebView2)

Producing a distribution locally

just publish            # → dist/KeepPressing       (x64)
just publish arch=arm64 # → dist/KeepPressing-arm64

The resulting dist/KeepPressing/ folder contains KeepPressing.exe plus the bundled runtime — that folder is the portable app. The release pipeline zips this same folder; see Release Process.


Related: Building & Tasks · Release Process

Clone this wiki locally