Windowsアプリの1ファイル配布 - シングルバイナリとOS依存の限界

· 更新日: · · Windows, 配布, シングルバイナリ, .NET, C++, WebView2, WinUI

更新履歴(3件・最終更新 2026年08月02日)

この記事に加えた変更の記録です。アーカイブした更新前のバージョンは、DOI付きの固定URLから読めます。

記事の冒頭に「この記事の知識マップ」節を追加しました。本文で扱っている概念とその関係を、要約・図・詳細ページへのリンクにまとめたものです。本文の主張は変えていません。
外部レビュー(1283件)への対応として本文を更新しました。個々の変更内容は、この下の履歴を参照してください。
`/MT`と`/MD`の対比表と`dotnet publish`の3パターンを追加し、レベルA〜Dを階層図にしました。用語表を追加し、single-fileの起動時展開の挙動、`Assembly.Location`が空文字列になるなどのAPI非互換、Native AOTの制約(動的読み込み不可、C++/CLI不可、組み込みCOM不可)、EvergreenとFixed Versionの対比を追記しました。
初版公開
この記事を引用する(DOI: 10.5281/zenodo.21589706)

この記事はZenodoにアーカイブされています。常に最新版へ解決されるDOIと、いま表示している版に固定されたDOIの両方を下に示します。

小村 豪(2026)「Windowsアプリの1ファイル配布 - シングルバイナリとOS依存の限界」合同会社小村ソフト. https://doi.org/10.5281/zenodo.21589706 https://staging.comcomponent.com/blog/2026/03/19/003-windows-single-binary-and-os-dependencies/

DOI(最新版)
10.5281/zenodo.21589706
DOI(この版)
10.5281/zenodo.21732728

この記事は、「Windows では、どこまでを シングルバイナリ と言っていいのか」という雑談から始まりました。きっかけになった投稿は次のものです。ここを読み飛ばしても、以降は単独で読めるように書いています。

Windows で「できれば 1 ファイルで配りたい」は、かなり普通の要望です。社内ツール、装置連携ツール、監視端末、オフライン環境、インストーラを極力避けたい現場では、シングルバイナリ化 はとても魅力があります。

ただ、この話は最初に切り分けておかないと、だいたい途中で噛み合わなくなります。Windows で言う「シングルバイナリにしたい」には、実は 4 つの別々の話が混ざりやすいからです。

  • 配布物を 1 個にしたい
  • .NET や Visual C++ のランタイムを事前インストール不要にしたい
  • インストーラや管理者権限なしで置くだけで動かしたい
  • 対象 Windows の違いに依存したくない

この 4 つは同じではありません。実務的には、こう考えるのが一番ずれません。

配布物を 1 EXE に寄せることはかなりできる。 でも、対象 Windows への依存をゼロにすることはできない。

この記事では、その境界線を Windows アプリの実務向けに整理します。

1. まず結論

最初に結論だけまとめると、こうです。

  • 普通のデスクトップ EXE なら、かなり高いところまで single binary 化できます
  • ただし、1 EXE にできること対象 Windows に依存しないこと は別です
  • Shell 拡張、Windows サービス、ドライバ、WebView2、WinUI 3 の一部は、ファイル数より OS へ何を登録し、何を前提にするか のほうが本題になりやすいです
  • 実務で一番大事なのは、single binary 化したいのか、インストーラ不要にしたいのか、OS 依存を減らしたいのか を分けて決めることです

言い換えると、Windows での線引きはこうなります。

  • 配布物を 1 個に寄せる: かなり可能
  • 追加ランタイムを抱え込む: かなり可能
  • xcopy 配布に寄せる: アプリ種別による
  • 対象 Windows 側の依存を消す: 不可能

1.1 この記事で使う用語

先に、以降で何度も出てくる言葉だけ整理しておきます。

用語 読み方・展開 この記事での意味
UCRT Universal C Runtime Visual Studio 2015 で C ランタイムが分割されてできた、標準 C ライブラリ部分。Windows 10 以降では OS の構成要素として同梱されています
VC++ 再頒布可能パッケージ Visual C++ Redistributable UCRT 以外の Visual C++ ランタイム DLL を対象機に入れるためのインストーラ
framework-dependent 対象環境の .NET に依存する配布 対象機に .NET ランタイムが入っている前提の配布形態
self-contained .NET ランタイム同梱 アプリ側が .NET ランタイム一式を抱えて配る形態
single-file 単一ファイル発行 配布物を 1 個の EXE にまとめる .NET の発行オプション
Native AOT Native Ahead-Of-Time 発行時に IL をネイティブコードへ事前コンパイルする配布形態。実行時に JIT を使いません
app-local 配布 アプリ隣接配布 DLL を EXE と同じフォルダーに置き、そのアプリからだけ使う配り方
xcopy 配布 コピーするだけの配布 インストーラも管理者権限も使わず、フォルダーごと置けば動く配り方
SCM Service Control Manager、サービス制御マネージャー Windows サービスの登録・起動・停止を管理する OS の仕組み
UAC User Account Control、ユーザー アカウント制御 管理者権限への昇格を制御する Windows のセキュリティ機構
Shell 拡張 シェル拡張 エクスプローラーなどのプロセスへ読み込まれて動く COM コンポーネント
Evergreen 常時更新方式 WebView2 Runtime を自動更新される共有の 1 本に任せる配布モード
Fixed Version 版固定方式 特定バージョンの WebView2 Runtime を自分のアプリに同梱する配布モード
arch architecture、CPU アーキテクチャ x86 / x64 / Arm64 のこと

この記事の知識マップ

Windowsアプリは配布物を1個のEXEへ寄せること自体はかなり可能で、.NETのself-containedやsingle-file・Native AOT、C/C++の静的リンク(/MT)が使えるが、OSバージョンやアーキテクチャ、システムDLL、セキュリティモデルへの依存は残り、対象Windowsへの依存をゼロにはできない。self-containedとframework-dependentは排他的な選択肢で、Native AOTは実質single-fileとして動く代わりに組み込みCOMなどが使えなくなる。WebView2はEvergreenかFixed Versionかでランタイムの提供方法を選ぶ必要があり、WinUI 3はpackaged(MSIX)かunpackagedかでPublishSingleFileの可否が変わる。Shell拡張やドライバーは登録・署名の設計が本題になるため、無理に1EXEへ圧縮するよりapp-local配布のほうが保守しやすいことが多い。

Windowsアプリのシングルバイナリ化の知識マップ配布物を1個にすることとOSへの依存を消すことが別の軸であること、.NETとC/C++それぞれの単一ファイル化手段、WebView2やWinUI 3のようなホスト統合が配布方式そのものを制約することを示す図前提とする両立しない両立しない前提とする前提とする両立しない前提とする利用する利用する両立しない利用する前提とするで構成できるで構成できる両立しない利用する前提とする用いるのは非推奨推奨される対応前提とする利用する前提とするシングルバイナリ化(1ファイル配布)対象Windowsへの依存self-contained発行framework-dependent発行(.NET)Native AOTbuilt-in COM interopsingle-file発行(.NET)CRTの静的リンク(/MT)CRTの動的リンク(/MD)Visual C++ 再頒布可能パッケージUCRT(Universal C Runtime)MSIXパッケージング(packaged)WinUI 3 / Windows App SDKMicrosoft Edge WebView2WebView2 RuntimeEvergreen配布モード(WebView2)Fixed Versionランタイムシェル拡張(エクスプローラー拡張)COM(コンポーネントオブジェクトモデル)ドライバー署名ドライバーパッケージapp-local配布(アプリ隣接配布)

図の実線は常に成り立つ関係、破線は条件付きの関係です(成立条件は詳細ページの各関係の説明に記載)。関係すべての一覧(全22件、根拠・確度つき)と主要概念の定義は知識マップ詳細ページにまとめています。データ: JSON-LD / Turtle

2. 「シングルバイナリ」は 4 段階に分けて考える

段階を先に図にすると、こうなります。下から順に難しくなり、一番上は Windows では到達できません。

レベル A: 配布物が 1 個かなり可能レベル B: 言語ランタイムの事前インストールが不要かなり可能レベル C: インストールや登録が不要アプリ種別によるレベル D: 対象 Windows に依存しないWindows では到達できない

「シングルバイナリにしたい」という話は、この 4 段のうちどこを指しているのかで、必要な作業がまったく変わります。

2.1 レベル A: 配布物が 1 個

一番表面的なのはこれです。

  • メールで 1 個送れる
  • USB に 1 個置けばよい
  • 展開先に app.exe だけ置く

これは 見た目の配布単位 の話です。実際には起動時に一時展開していても、OS 側の DLL に依存していても、この条件だけなら満たせます。

2.2 レベル B: 言語ランタイムの事前インストールが不要

次は、対象マシンにあらかじめ .NET ランタイムや VC++ 再頒布可能パッケージを入れなくても動く状態です。

  • C/C++ の静的リンク
  • .NET の self-contained
  • .NET の single-file
  • .NET Native AOT

このレベルになると、「単体で持っていける」感じはぐっと強くなります。

2.3 レベル C: インストールや登録が不要

ここから急に難しくなります。

単なる EXE なら、置くだけで動くことがあります。でも、こういうものは別です。

  • Shell 拡張
  • Windows サービス
  • カスタム URL スキームやファイル関連付け
  • ドライバ
  • Explorer や Office など、他プロセスに読み込まれるコンポーネント

この領域は ファイルを置くだけ では済みません。OS 側の登録や、ホスト側との結線が必要です。

2.4 レベル D: 対象 Windows に依存しない

これは Windows では無理です。

Windows アプリは最終的に Windows の API、ローダー、セキュリティモデル、デバイススタックの上で動くからです。single binary 化できるのは、アプリ側の責任範囲まで です。OS 自体まで持っていくわけではありません。

3. かなり 1 EXE にしやすい領域

Windows でも、比較的 1 EXE に寄せやすいアプリはあります。

  • 単独起動されるデスクトップツール
  • EXE 自身が UI と処理を持つ業務アプリ
  • 通信、ファイル処理、ログ収集、監視、装置制御のようなツール
  • Explorer や Office のホスト統合を必要としないもの
  • Web ランタイムを前提にしない UI

このタイプなら、アプリ本体に含めやすいものは多いです。

  • 自前コード
  • リソース
  • マニフェスト
  • 既定設定
  • テンプレートデータ
  • 一部のサードパーティ ライブラリ
  • 言語ランタイム本体

さらに、DLL を完全に EXE 内へ埋め込まなくても、EXE の隣に DLL を置く app-local 配布 は Windows では普通に有力です。実務では、

  • app.exe 1 個
  • または app.exe + 隣接 DLL 数個
  • ただしインストーラ不要、管理者権限不要、xcopy で配れる

この形のほうが、無理に 1 EXE へ圧縮するより保守しやすいことが珍しくありません。

4. 1 EXE でも消えない Windows 依存

「EXE 1 個なら、対象 Windows に依存しない」と思ってしまうと、ここで事故ります。実際には、1 EXE にしても残る依存があります。

4.1 OS バージョン依存

Windows API にはそれぞれ最低サポート OS があります。x64 / Arm64 の違いもあります。つまり単一 EXE にしても、

  • Windows 10 まで動くのか
  • Windows 11 前提なのか
  • Windows Server でも動かすのか
  • x86 / x64 / Arm64 のどれを対象にするのか

は最初に固定する必要があります。

4.2 システム DLL 依存

こちらが 1 EXE にしたつもりでも、実行時には当然ながら OS 提供のコンポーネントを使っています。

  • kernel32.dll
  • user32.dll
  • advapi32.dll
  • COM 基盤
  • サービス制御基盤

このあたりは Windows 側の責任範囲です。

4.3 セキュリティモデル依存

  • UAC
  • ファイル ACL
  • サービス制御マネージャ
  • レジストリ
  • ドライバ署名ポリシー

こうしたものは、アプリが単独で抱え込めません。

4.4 ホストやランタイム依存

単独起動 EXE ではなく、何かのホストに載る設計だと依存は一気に増えます。

  • WebView2 を使う: WebView2 Runtime が要る
  • WinUI 3 / Windows App SDK を使う: 配布モードの整理が要る
  • Shell 拡張を作る: Explorer 側への登録が要る

つまり、UI や統合の選択が、そのまま配布の難しさになる ことが多いです。

5. 技術別に見る現実的な落としどころ

5.1 ネイティブ C/C++

ネイティブ C/C++ は、single binary 化の自由度が高い側です。静的リンクを選ぶ余地があり、単独起動 EXE ならかなり寄せやすいです。

ただし、全部を 1 ファイルに押し込むことより、

  • UCRT や VC++ ランタイムをどうするか
  • サードパーティ DLL を app-local に置くか
  • 対象 CPU / OS をどこまで絞るか

のほうが実務上は重要です。

入口: /MT/MD の違い

MSVC で「ランタイムを抱えるかどうか」を決めているのは、実質このコンパイラ オプションです。

オプション リンクされるもの 対象機に必要なもの
/MD ucrt.libvcruntime.lib という DLL 用インポート ライブラリ。実行時は ucrtbase.dllvcruntime<バージョン>.dll を使う UCRT と VC++ ランタイム
/MT libucrt.liblibvcruntime.liblibcmt.lib を静的リンク 追加ランタイムなし

最小の試し方は、Developer Command Prompt でこれだけです。

cl /std:c++17 /EHsc /O2 /MT app.cpp /Fe:app.exe

ここで注意したい点が 3 つあります。

  • UCRT は Visual Studio 2015 で C ランタイムが分割されたときに Windows の構成要素 になり、Windows 10 以降には OS の一部として同梱されています。それより前の Windows を対象にするなら、vcredist での再頒布が要ります。
  • DLL 側を /MT で作るのは推奨されません。 静的リンクした CRT は状態がその DLL の中だけに閉じるため、EXE と DLL でメモリ確保やロケール、_set_se_translator の効き方がずれます。「EXE は /MT、同梱 DLL も /MT」と雑に揃えると、境界をまたいだ確保・解放で事故ります。
  • /clr/MT は併用できません。C++/CLI が混ざるなら /MD 側です。

5.2 .NET

.NET は single-fileself-containedNative AOT があるので、見た目の配布単位はかなり小さくできます。

ただし区別は必要です。

  • framework-dependent: 対象環境の .NET に依存
  • self-contained: .NET ランタイムを抱える
  • single-file: 配布物を 1 つへ寄せる
  • Native AOT: さらに起動時依存を減らすが、機能制約もある

「single-file だから OS 依存が減る」わけではありません。減るのは主に アプリ配布物のまとまり です。

入口: dotnet publish の 3 パターン

まず動かして違いを見るなら、この 3 本で足ります。

rem 1. framework-dependent + single-file: 対象機に .NET ランタイムが要る
dotnet publish -c Release -r win-x64 --self-contained false -p:PublishSingleFile=true

rem 2. self-contained + single-file: .NET ランタイムを抱える
dotnet publish -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true

rem 3. Native AOT: csproj に PublishAot を書いたうえで発行する
dotnet publish -c Release -r win-x64

PublishSingleFilePublishAot は、コマンドラインではなく csproj に書くほうが公式の推奨です。ビルド中の互換性解析が有効になり、発行してから気づく事故が減るためです。

<PropertyGroup>
  <PublishSingleFile>true</PublishSingleFile>
  <PublishAot>true</PublishAot>
</PropertyGroup>

なお RuntimeIdentifier を指定すると SelfContained は既定で true になります。framework-dependent にしたいときは --self-contained false を明示してください。Native AOT を Windows で発行するには、Visual Studio の C++ によるデスクトップ開発 ワークロードが要ります。

トレードオフ: 「1 個にする」は無料ではない

ここは「できる」だけ書くと事故るので、代償のほうも並べておきます。

single-file の起動時展開

  • 既定では、バンドルされるのは managed DLL だけです。起動時にメモリ上へ読み込まれ、フォルダーへは展開されません。ランタイム本体のネイティブ バイナリは別ファイルのまま残ります。
  • ネイティブ バイナリまで 1 個に含めたいなら IncludeNativeLibrariesForSelfExtract、全部を実行前に展開させるなら IncludeAllContentForSelfExtract を使います。どちらも「展開してから起動する」動作 になり、Windows では %TEMP%\.net の下へ展開されます。DOTNET_BUNDLE_EXTRACT_BASE_DIR で場所を変えられますが、権限の違うユーザーやサービスから書ける場所にしないでください。
  • EnableCompressionInSingleFile を有効にすると EXE はかなり小さくなりますが、起動時にメモリ上で伸長するぶん起動が遅くなります。公式も「使う前にサイズと起動コストの両方を測れ」という書き方をしています。影響はアプリによって大きく変わります。

single-file の API 非互換

配布物を 1 個にすると、ファイルパス前提のコードが静かに壊れます。

API single-file での挙動
Assembly.Location 空文字列を返す
Assembly.CodeBase PlatformNotSupportedException
Assembly.GetFile IOException
Module.Name <Unknown> という文字列を返す

EXE の隣のファイルを触るなら AppContext.BaseDirectory、実行ファイルのパスが要るなら Environment.ProcessPath に寄せます。サードパーティ製ライブラリが内部でこれらを使っていることもあるので、single-file 化したら 一度は実機で起動確認 が要ります。

Native AOT の機能制約

「起動が速く、ランタイム不要」の代わりに、次が使えなくなります。

  • Assembly.LoadFile のような 動的読み込み
  • System.Reflection.Emit のような 実行時コード生成
  • C++/CLI
  • Windows では 組み込み COM
  • トリミングが必須なので、トリミングの制約もそのまま乗ります
  • 実質 single-file なので、上の API 非互換もそのまま乗ります
  • System.Linq.Expressions は常にインタープリタ動作になり、実行時生成コードより遅くなります

対象プラットフォームも決め打ちです。.NET 8 では Windows は x64 と Arm64、.NET 9 以降で x86 が加わりました。「AnyCPU で 1 個」という発想は最初から成立しません。

5.3 WebView2

WebView2 を採用すると、single binary の難しさはがらりと変わります。ここでの本題は EXE の数ではなく、WebView2 Runtime をどう扱うか です。

「1 EXE にできるか」より先に、考えるべき問いがあります。

  • Runtime を既存環境前提にするか
  • Evergreen を使うか
  • Fixed Version を同梱するか
  • オフライン配布でどこまで責任を持つか

Evergreen と Fixed Version の違いは、ざっくりこうです。

  Evergreen Fixed Version
更新するのは Microsoft。自動更新される 自分。アプリの更新に合わせて入れ替える
端末上の実体 全アプリで 1 本を共有 アプリごとに同梱
配布サイズ ほぼ増えない 250 MB を超える
入れ方 Bootstrapper は約 2 MB で、必要なぶんをダウンロードする。オフラインなら Standalone Installer を同梱する 展開したバイナリ一式をアプリと一緒に配る
既存の制約 端末に入っているか、起動前に確認する必要がある ネットワーク経路や UNC パスからは実行できない

Evergreen Runtime は Windows 11 には OS の一部としてプリインストールされています。ただし Windows 10 側には入っていない端末も残るため、Microsoft 自身も「Evergreen を選んでも Runtime は配布したほうがよい」という書き方をしています。つまり アプリ側で有無を確認して足りなければ入れる 手順は、どちらにしても要ります。Fixed Version は「更新のタイミングを自分で握れる」代わりに、配布物が数百 MB 増えます。1 EXE の話とは別に、ここを先に決める必要があります。

5.4 WinUI 3 / Windows App SDK

WinUI 3 も、採用した時点で配布要件が変わります。UI 技術の選択が、そのまま配布方式の選択になります。

具体的には、決めるものが 2 軸あります。

  • packaging: packaged(MSIX)か、外部の場所を指す packaged か、unpackaged か
  • runtime: framework-dependent か self-contained か

そして single binary の観点で効いてくるのが、この組み合わせ制約です。

  • PublishSingleFile が使えるのは unpackaged かつ self-contained の WinUI 3 アプリだけで、Windows App SDK 1.5 以降が要ります。
  • packaged なアプリ、および外部の場所を指す packaged なアプリでは PublishSingleFile は使えません。
  • unpackaged にすると package identity を失うので、通知、バックグラウンド タスク、ファイル関連付け、コンテキスト メニュー拡張といった、package identity を前提にした Windows 機能は使えなくなります。

つまり WinUI 3 では、「1 EXE にする」と「Windows の拡張機能を使う」が 正面からぶつかります。single binary を最優先にするなら、最初に UI 技術の前提を見直す ほうが早いことがよくあります。

6. 本質的に「登録・依存」が必要な領域

6.1 Shell 拡張

Explorer に読み込まれる Shell 拡張は、単なる「置くだけ EXE」とは別物です。ここはファイル数より、Explorer へどう登録するか が本題です。

6.2 Windows サービス

サービス本体の exe 自体は 1 ファイルにできても、配布は別問題です。

  • SCM への登録
  • 権限
  • 起動アカウント
  • 復旧設定

を考える必要があります。つまりサービスは、「1 EXE にする」より「どうインストールするか」を詰める領域です。

6.3 ドライバ

ドライバはさらに明確です。INF、署名、インストール手順まで含めて成立するので、single binary の土俵に最初から乗りにくいです。

7. 実務での判断表

ざっくり判断するなら、この表が使いやすいです。

作りたいもの 1 EXE 現実度 先に考えるべきこと
単独起動の Win32 / C++ ツール 高い 静的リンク、対象 OS / arch
単独起動の WinForms / WPF ツール 高い self-contained、single-file、Native AOT の適性
WinUI 3 / Windows App SDK アプリ 配布モード、追加依存
WebView2 ベースのデスクトップ UI 低から中 Runtime の配布方式
Explorer 右クリック拡張やプレビュー 低い COM / レジストリ登録
Windows サービス SCM 登録、権限、更新手順
ドライバ同梱アプリ 低い INF、署名、インストール

この表で一番大事なのは、「バイナリの数」と「配布の責任範囲」は別 だと分かることです。

8. 配布設計で先に決めるべきこと

single binary 化を成功させたいなら、実装より前に決めておきたいことがあります。

8.1 何を 1 個にしたいのかを決める

  • 配布物を 1 個にしたいのか
  • ランタイム事前インストールをなくしたいのか
  • インストーラ不要にしたいのか
  • オフライン更新を簡単にしたいのか

この答えによって、選ぶ技術は変わります。

8.2 最低サポート Windows と arch を最初に固定する

single-file も Native AOT も、基本的に OS / architecture specific です。ここを曖昧にしたまま「とにかく 1 ファイルで」と進めると、最後に API 不足や runtime 不一致で詰まります。

8.3 「同梱するもの」と「Windows に任せるもの」を明文化する

実務では、この表を書いておくだけでかなり事故が減ります。

  • アプリに同梱するもの
    • 本体 exe
    • 自前 DLL
    • 設定テンプレート
    • self-contained runtime
  • Windows に任せるもの
    • システム DLL
    • OS API
    • SCM / レジストリ / Explorer
    • ドライバ基盤
  • 別途前提とするもの
    • WebView2 Runtime
    • VC++ Redistributable
    • Office / Excel
    • 専用ドライバ

8.4 single binary を優先するなら、ホスト統合を減らす

これはかなり効きます。

  • Shell 拡張をやめて普通の EXE にする
  • サービス化せず、タスクスケジューラや明示起動で済ませる
  • WebView2 ではなくネイティブ UI を使う
  • COM は自プロセス内で閉じる

要するに、OS に「読み込ませる」「登録する」設計を減らす ほど、single binary に近づきます。

9. まとめ

Windows における single binary 化は、かなりのところまで可能です。ただし、行き着くところはこの一文です。

アプリを 1 EXE にすることはできる。 でも、そのアプリが依存する Windows まで 1 EXE にすることはできない。

特に覚えておきたい点を 5 つ挙げます。

  • 単独起動の普通の EXE なら、相当なところまで 1 ファイル配布へ寄せられる
  • C/C++ の静的リンク、.NET single-file、Native AOT は有力
  • ただし OS バージョン、arch、システム DLL、セキュリティモデルへの依存は消えない
  • Shell 拡張、サービス、ドライバ、WebView2、WinUI 3 の一部は、OS 登録や追加ランタイムの話が本体になる
  • single binary の成否は、「何を 1 個にしたいのか」を最初に切り分けることで決まる

もし single binary を強く優先するなら、技術選定の時点で OS との結合度を下げる 方向で設計したほうが、はるかに成功しやすいです。

10. 参考資料

同じタグを共有する最新の記事です。さらに近い話題で知識を深められます。

このテーマと近いトピックページです。記事を起点に、関連するサービスや他の記事へ進めます。

この記事は次のサービスページにつながります。近い入口からご覧ください。

よくある質問

この記事のテーマについて、相談時によくある質問をまとめています。

Windowsアプリを1つのEXEファイルだけで配布できますか?
単独起動されるデスクトップツールであれば、かなり高いところまで可能です。C/C++の静的リンク、.NETのself-containedやsingle-file、Native AOTを使えば、配布物を1個のEXEに寄せられます。ただし、1EXEにできることと、対象Windowsに依存しないことは別の話で、OSバージョン・アーキテクチャ・システムDLL・セキュリティモデルへの依存は消えません。
.NETのsingle-fileにすればOS依存はなくなりますか?
なりません。single-fileで減るのは主にアプリ配布物のまとまりで、OS依存が減るわけではありません。framework-dependentは対象環境の.NETに依存し、self-containedは.NETランタイムを抱え、Native AOTは起動時依存をさらに減らせますが機能制約もあります。single-fileもNative AOTも基本的にOS・アーキテクチャ固有なので、最低サポートWindowsとarchは最初に固定する必要があります。
1EXEにしにくいのはどんなアプリですか?
Shell拡張、Windowsサービス、ドライバ、WebView2ベースのUI、WinUI 3の一部です。これらはファイル数よりも、OSへの登録や追加ランタイムの扱いが本題になります。たとえばShell拡張はExplorerへの登録が必要で、サービスはSCMへの登録・権限・起動アカウントの設計が要り、ドライバはINFと署名まで含めて成立するため、置くだけの配布は成立しません。WebView2はWebView2 Runtimeの配布方式を先に決める必要があります。
無理に1EXEへ埋め込むより良い配布方法はありますか?
EXEの隣にDLLを置くapp-local配布が有力です。app.exeに隣接DLL数個という形でも、インストーラ不要・管理者権限不要でxcopy配布できるなら、無理に1EXEへ圧縮するより保守しやすいことが珍しくありません。重要なのは、配布物を1個にしたいのか、ランタイムの事前インストールをなくしたいのか、インストーラを不要にしたいのかを最初に切り分けることです。

著者プロフィール

記事の著者プロフィールページです。

小村 豪

合同会社小村ソフト 代表

Windows ソフト開発、技術相談、不具合調査を中心に、既存資産が残る案件や原因が見えにくい障害調査に強みがあります。

ブログ一覧に戻る