MSI / MSIX / ClickOnce / xcopy は同じ土俵じゃないと知った話 ~配布方式と更新責任を分けて考える~
導入
私はSasaki。Windowsクライアントの配布設計と保守を長くやっている、少し口うるさい先輩だ。
リリース前の設計レビューで、後輩の Go(22歳)が、妙にすっきりした顔でノートPCを開いた。
「Sasakiさん、配布方式、もう整理できました。
更新があるなら、結局アプリ側で取りに行くのが最強じゃないですか。
最初だけ何かで入れて、以後は共通の独自 updater で全部回せば、運用もそろいます」
彼の勢いは嫌いではない。
ただ、Windows アプリの“配る”は、実装の最後に付ける包装紙みたいに見えて、実はかなり早い段階で案件の性格を決める。
今回、同時に出そうとしていたのは次の4つだった。
- 24時間動く監視本体。Windows service あり。共有PCに machine-wide で入れる
- 社内の担当者が使う検査票入力ツール。標準ユーザーで入れたい
- 客先の閉域環境へ USB で持っていくログ採取ツール。置くだけで動いてほしい
- Windows 11 前提の新しい作業支援アプリ。通知や Windows 統合を少し取り込みたい
この時点で、もう匂いがした。
「全部同じ」で幸せになれる並びではない。
配布の話をしているはずなのに、5分後には権限、サービス、USB、更新事故の話に飛ぶ。
Windows デスクトップは、だいたいそういう世界である。
Goが最初に持ってきた「全部これで更新できる」設計
Go が最初に置いていた判断は、だいたいこんな感じだった。
string ChooseDeployment(AppProfile app)
{
if (app.HasFrequentUpdates)
return "CustomUpdater";
if (app.IsWindows11Only)
return "MSIX";
if (app.IsInternalTool)
return "ClickOnce";
if (app.NeedsNoInstall)
return "XCopy";
return "MSI";
}
一見、整理されているように見える。
だが、Windows アプリの配布としては、いちばん大事な軸が混ざっていた。
抜けていたのは、たとえばこのあたりだ。
- current user に入れればよいのか、machine-wide に入れる必要があるのか
- service / driver / shell extension / COM 登録のような OS 統合があるのか
- 欲しいのが
自動更新なのか、package identityなのか - 閉域・オフライン・USB 配布に耐える必要があるのか
- 更新を built-in の仕組みに寄せたいのか、自分たちで運用責任まで持ちたいのか
要するに Go は、最初にどう入れるか と その後どう新しい版へ連れていくか を、同じ if 文に押し込めていた。
これをやると、話がかなり危ない方向へ進む。
初回導入の設計と、継続更新の設計は、似ているようで別物だからだ。
その案件、配布先は本当に1種類だったか
私はいったん Go の資料を閉じて、対象アプリを1つずつ並べ直した。
1. 監視本体
- 共有PCで使う
- Windows service がある
- 全ユーザーが同じ構成を使う
- 運用担当が「どこに入り、どう消えるか」を説明できる必要がある
この時点で、かなり MSI 寄りだ。
少なくとも、「置けば動く」で済ませる話ではない。
2. 検査票入力ツール
- 社内向け
- .NET デスクトップアプリ
- 標準ユーザーで入れたい
- 更新頻度はやや高め
- OS への深い統合は薄い
これは ClickOnce の匂いが強い。
「社内向け」「per-user」「更新込みで素早く回したい」は、今でもかなり ClickOnce が得意な場所だ。
3. ログ採取ツール
- 客先の閉域環境
- USB で渡す
- 管理者権限を期待しにくい
- 1つ前の版を残したい
これは xcopy がかなり素直だ。
インストーラの賢さより、フォルダ差し替えの単純さが勝つ。
4. 作業支援アプリ
- Windows 11 前提
- install / uninstall の後始末をきれいにしたい
- 通知や Windows 側の機能を取り込みたい
- 配布元と更新経路をある程度きれいにしたい
ここは MSIX をちゃんと比較対象に入れる理由がある。
package identity が効くなら、MSIX の価値は急に上がる。
つまり、同じ「Windows アプリ群」でも、配布の主題は全然そろっていなかった。
見た目をそろえる話と同じで、配布方式も 全部同じ に寄せると、どこかのアプリが不自然な我慢を始める。
配布の話と更新の話が分かれた瞬間、会議が静かになった
私は打ち合わせのあと、Go に1本の記事を送った。
Windows アプリの配布方式をどう選ぶか - MSI / MSIX / ClickOnce / xcopy / 独自 updater の判断表
https://comcomponent.com/blog/2026/03/20/000-windows-app-deployment-msi-msix-clickonce-xcopy-custom-updater/
翌朝、Go は前日より少し静かな声で言った。
「独自 updater って、最初に選ぶ“配布形式”じゃないんですね。
MSI / MSIX / ClickOnce / xcopy は どう入れるか の話で、独自 updater は 更新をどこまで自前で引き受けるか の話なんだ……」
そこが分かると、配布会議がいきなり楽になる。
Windows アプリの配布でよくある混乱は、だいたいここから始まる。
- MSI と MSIX と ClickOnce と xcopy を、全部「インストーラの見た目違い」みたいに並べる
- その横に独自 updater まで置いて、同じレイヤーの選択肢だと思ってしまう
- さらに
self-containedやframework-dependentの話まで混ぜて、論点が増殖する
ここは2段に分けたほうがいい。
-
最初にどう入ってもらうか
MSI / MSIX / ClickOnce / xcopy -
入ったあと、どう更新を回すか
MSIX の更新モデル / ClickOnce / 手動差し替え / 独自 updater
この2段に切り分けるだけで、かなり霧が晴れる。
レビューで最後に置いた判断表
最終的に、会議では次の表を置いた。
| 状況 | まず選ぶもの | 見る理由 |
|---|---|---|
| 全ユーザー向け、service や COM 登録、machine-wide な設定がある | MSI | Windows の伝統的な install / uninstall の流儀に乗せたほうが説明しやすい |
| Windows 10 / 11 前提で、後始末のきれいさや package identity が大事 | MSIX | modern packaging と Windows 側の機能を活かしやすい |
| .NET の社内向け業務アプリを per-user で軽く配りたい | ClickOnce | 標準ユーザー配布と built-in 更新の相性がよい |
| 閉域、USB、置くだけ、管理者権限なしを優先したい | xcopy | 単純で、壊れ方と戻し方が分かりやすい |
| 更新 UX、チャネル、段階配信、rollback まで自分たちで握りたい | 独自 updater | 仕組みより運用責任を自前に寄せる価値がある |
この表でいちばん大事なのは、更新がある だけで独自 updater に飛ばないことだ。
更新があるアプリは大量にある。
だが、更新事故の復旧や配信チャネルまで自前で面倒を見るべきアプリは、そこまで多くない。
結局この案件はどうしたか
結論として、この案件は次のように分けた。
- 監視本体は MSI
- service と machine-wide 導入が主題だった
- まずは月次更新なので、更新 UX を自前で作り込まない
- 検査票入力ツールは ClickOnce
- 社内向け / per-user / 標準ユーザー / 頻繁な更新に素直だった
- ログ採取ツールは xcopy
- USB 配布と side-by-side 運用がいちばん大事だった
- 作業支援アプリは MSIX
- Windows 11 前提で、package identity を使う価値があった
- 共通の 独自 updater は今回は見送った
- まだ
チャネル運用や段階配信が製品要件ではなかった - そこまで背負う理由が、今はなかった
- まだ
レビューの最後に、Go が少し苦笑いしながら言った。
「配布方式って、最後に箱を作る話じゃなくて、アプリが OS とどの玄関で握手するかを決める話だったんですね」
そう。
Windows アプリの配布は、最後のひと手間ではない。
意外とかなり早い段階で、設計の骨格に触っている。
MSI が基準点になる場面
MSI は、雑に「古いインストーラ」で片付けると損をする。
向いているのは、たとえばこういう場面だ。
- 全ユーザー向けに入れる
- Windows service を含む
- COM 登録や file association がある
- machine-wide な設定や前提物の導入を整理したい
- install / uninstall / repair を Windows の流儀で扱いたい
MSI の強みは、アプリを OS にどう入れたかを説明しやすいことだ。
特に、運用担当や情シスに「何を登録し、どう消え、どこまで直せるか」を話す必要があるとき、ここはかなり大きい。
もちろん、楽な道具ではない。
upgrade 設計を雑にすると後で苦しむし、custom action を増やしすぎると壊れやすい。
ただ、それは MSI が悪いというより、OS へ深く入れる案件そのものが重い、ということでもある。
MSIX が意味を持つ場面
MSIX が効くのは、単に新しい installer だからではない。
package identity を持ち、導入・削除・更新まわりを Windows の今の流儀に寄せたいときだ。
特に意味が出やすいのは、こういうときである。
- Windows 10 / 11 前提にできる
- update / uninstall をきれいにしたい
- package identity 前提の Windows 機能を使いたい
- Intune や App Installer に寄せた運用をしたい
ここで混ざりやすいのが、Windows 11 の新しい拡張ポイントと、昔ながらの shell extension の話だ。
前者のように package identity が効く機能では MSIX の意味が大きい。
だが、Explorer の中に DLL を読み込ませるような classic な in-process shell extension は、むしろ最初に警戒したほうがいい。
MSIX は 何でも入る上位互換 ではない。
たとえば次のような荷物は、最初に確認したほうが安全だ。
- driver
- classic な in-process shell extension
- HKLM を自分の庭のように書き換える古い構成
- インストールフォルダへ自由に書き込む前提
- 常時昇格を前提にした動き
逆に、欲しいのが package identity や modern packaging の価値なら、MSIX はかなり強い。
Windows 11 前提の新しい製品では、ここが決め手になることがある。
ClickOnce が今でもかなり強い場面
ClickOnce は、妙に過小評価されやすい。
だが、.NET の社内向けデスクトップアプリでは、まだ普通に強い。
向いているのは次だ。
- 社内向け業務アプリ
- 標準ユーザーで導入したい
- per-user で十分
- 更新込みで早く回したい
- 更新 UI をそこまで自作したくない
この領域では、ClickOnce はかなり素直だ。
「情シスに毎回管理者権限をお願いしたくない」
「担当者ごとに使い始めてもらいたい」
「新版が出たら、なるべく自然に追従してほしい」
この3つがそろうと、ClickOnce は今でも強い。
逆に、OS へ深く触る役目まで期待しないほうがいい。
service や driver、複雑な machine-wide セットアップまで背負わせると、だんだん苦しくなる。
xcopy がいちばん平和な場面
xcopy は、セットアップを賢くする方式ではない。
フォルダそのものを配布単位にして、そのまま使う方式だ。
その代わり、条件が合うと驚くほど強い。
たとえばこういうものにはよく合う。
- 診断ツール
- 装置設定ツール
- ログ採取ツール
- 閉域で USB 配布したいユーティリティ
- 複数版を side-by-side で共存させたいもの
xcopy の強さは、賢さではなく単純さにある。
- フォルダを置く
- だめなら前のフォルダへ戻す
- 旧版を残したければそのまま残す
この戻しやすさは、本番でかなり効く。
当然、弱いところもはっきりしている。
- Start menu 連携
- ARP
- repair
- service / driver / shell extension
- built-in 更新
なので、xcopy は「雑な暫定運用」ではなく、条件が合うならかなり理にかなった正式解だと思ったほうがいい。
独自 updater を選ぶ前に見ること
独自 updater は、自由度の話に見えて、実際には“面倒を見る範囲”を自前に寄せる話だ。
欲しくなる理由はたしかにある。
- stable / beta / preview のチャネルを持ちたい
- 段階配信したい
- 背景ダウンロードや通知を細かく制御したい
- 更新 telemetry を取りたい
- 壊れた更新からの復旧まで自分たちで握りたい
ただし、これを選ぶなら、次も背負うことになる。
- 署名検証
- 配信 manifest
- 再試行 / resume
- proxy / firewall / 閉域対応
- rollback
- 壊れた更新の復旧
- updater 自身の更新
ここを小さく見積もると、だいたい後で痛い。
独自 updater は、MSI の代わり でも MSIX の代わり でもない。
多くの場合、MSI / MSIX / xcopy などで最初の導入を成立させたうえで、標準の更新モデルでは足りない要件があるときに追加で選ぶものだ。
最初の一手というより、最後の切り札に近い。
Goが捨てた4つの雑な思い込み
記事を読んでから、Go が捨てた思い込みは4つあった。
1. 更新があるなら独自 updater 一択
違う。
更新があることと、更新責任を自前で持つべきことは同じではない。
2. MSIX は MSI の上位互換
これも違う。
MSIX には強い価値があるが、driver や classic な shell extension のように、相性がはっきり悪い荷物もある。
3. self-contained なら配布設計は終わる
これも危ない。
ランタイムを同梱する話と、どう導入・更新・削除するかの話は別だ。
self-contained にすれば xcopy しやすくなる場面はある。
ただ、それだけで service や Start menu、repair、machine-wide 導入の問題が消えるわけではない。
4. 配布方式は最後に決めればいい
これがいちばん危ない。
service、package identity、標準ユーザー導入、閉域運用。
このへんは、あとから「やっぱり別方式にしましょう」でひっくり返すとかなり痛い。
Windows アプリでは、配布方式は実装の最後に乗せる包装紙ではない。
かなり早い段階で設計の前提になる。
迷ったときに最後に見る6問
最後に迷ったら、私は次の6問で絞る。
1. current user だけでよいか、machine-wide に入れる必要があるか
ここが最初の分かれ道だ。
2. service / driver / shell extension / COM 登録はあるか
ここが yes なら、まず MSI 側から考えることが多い。
3. package identity が必要な Windows 機能を使うか
ここが yes なら、MSIX の価値が一気に上がる。
4. 標準ユーザーだけで導入したいか
社内 .NET アプリなら、ClickOnce がかなり有力になる。
5. 更新頻度はどのくらいか。チャネルや段階配信まで必要か
ここで初めて、独自 updater の理由が出る。
6. 閉域か。USB 配布か。OS バージョンはそろっているか
閉域では、賢い仕組みより、誰でも戻せる単純さが勝つことがかなり多い。
この6問に答えるだけで、だいたい次に落ちる。
- 2 が yes → まず MSI 側
- 3 が yes → MSIX を優先比較
- 1 が current user、4 が yes、.NET デスクトップアプリ → ClickOnce
- 4 が yes、2 が no、置くだけ運用でよい → xcopy
- 5 が強く、更新 UX そのものを製品価値にしたい → 独自 updater
まとめ
Windows アプリの配布方式は、次の一文にかなり集約できる。
最初にどう入ってもらうかと、
入ったあと誰が更新を面倒見るかは、
別の問題として切り分ける。
ざっくり言うと、こうだ。
- MSI: OS と深く握手する desktop app
- MSIX: package identity と modern packaging の価値を取りたい app
- ClickOnce: per-user の .NET 業務アプリを軽く配って更新したい
- xcopy: 置くだけで十分な自己完結ツール
- 独自 updater: 更新そのものを製品機能として握りたい製品
あの日以降、Go は「更新あるんで updater 作りましょう」と先に言わなくなった。
代わりに、「誰に、どこへ、何を登録して、更新責任をどこまで持つか」を最初に話すようになった。
それでいい。
Windows アプリの配布方式は、インストーラの見た目を選ぶ作業ではない。
アプリと OS と運用の境界線を、どこに引くかを決める作業だ。
同じところで迷っているなら、元記事がかなり整理に効く。
補足リンク
- Windows Installer
https://learn.microsoft.com/en-us/windows/win32/msi/windows-installer-portal - Packaging overview for Windows apps
https://learn.microsoft.com/en-us/windows/apps/package-and-deploy/packaging/ - What is MSIX?
https://learn.microsoft.com/en-us/windows/msix/overview - App Installer file overview
https://learn.microsoft.com/ja-jp/windows/msix/app-installer/app-installer-file-overview - ClickOnce Deployment and Security
https://learn.microsoft.com/en-us/visualstudio/deployment/clickonce-security-and-deployment?view=visualstudio - Windows App SDK deployment overview
https://learn.microsoft.com/en-us/windows/apps/package-and-deploy/deploy-overview
(了)
Discussion