macOSで.NET SDKを更新したのに、dotnet sdk checkで「Patch が利用可能」と「Up to date」が同時に表示されて戸惑うことがあります。これは更新が失敗したのではなく、.NETが複数バージョンを並行インストールする設計だからです。.NET MAUI開発者向けに、表示の意味と正しい更新・整理の手順をまとめます。
dotnet sdk check で混乱しやすいポイント
dotnet sdk check(または dotnet --info / dotnet --list-sdks / dotnet --list-runtimes)を確認すると、次のような表示が並ぶことがあります。
.NET SDK:
8.0.xxx Patch 8.0.yyy is available
9.0.zzz Up to date
.NET Runtimes:
Microsoft.NETCore.App 8.0.10 Patch 8.0.12 is available
Microsoft.NETCore.App 9.0.1 Up to date
このとき「最新って書いてあるのに、同時にパッチがあると言われるのはなぜ?」「8.0.10にパッチを当てれば8.0.12になるの?」と感じがちです。しかし、ここで押さえるべき前提は1つだけです。
.NET SDK / Runtime は“上書き更新”ではなく、基本的にバージョンごとに並行(サイドバイサイド)で入る方式です。
表示メッセージの読み方(結論から逆引き)
まずはdotnet sdk checkに出てくるメッセージを「どう行動すべきか」で整理すると迷いません。
| 表示 | 意味 | 基本のアクション |
|---|---|---|
| Patch X is available | その系列(例:8.0.x)のより新しいパッチ版が存在する | その系列を使うなら、新しい版をインストールする(ワークロード更新とは別) |
| Up to date | その行に出ているバージョンは最新パッチ相当 | 基本的に対応不要(ただし別系列は別管理) |
| 複数行に同時表示 | バージョンが共存しているだけで、更新状態の矛盾ではない | 不要な旧版があるならアンインストールして整理 |
.NETの更新でまず押さえるべき全体像
混乱の原因は、.NETが「SDK」「Runtime」「Workload」という別物の集まりで、しかもそれぞれがサイドバイサイドで共存することにあります。まずは役割を分解して理解すると、dotnet sdk checkの表示が読みやすくなります。
| 要素 | 役割 | 代表的なバージョン表記 | 更新の考え方 | .NET MAUIへの影響 |
|---|---|---|---|---|
| .NET SDK | ビルド、テンプレート、MSBuild、CLI、ワークロード管理など開発に必要な一式 | 8.0.xxx / 9.0.xxx(SDK側の数字が大きい) | 新しいSDKを追加インストールしていく。複数版が共存する | MAUIプロジェクトのビルド・テンプレート適用に直結 |
| Runtime | アプリ実行環境(例:Microsoft.NETCore.App、Microsoft.AspNetCore.App など) | 8.0.10 → 8.0.12 のような月次パッチ | 新しいRuntimeを追加インストールする。通常は最新パッチへ繰り上げ | 実行・デバッグに影響。セキュリティ修正の適用に重要 |
| Workload | MAUI/Android/iOSなど、追加のSDK・パック・ツール群(maui など) | SDKに紐づいて更新される(同じSDKでも更新が必要な場合あり) | dotnet workload updateで更新(SDK本体の更新とは別) | MAUI開発では必須。SDK更新後にワークロード更新が必要になることがある |
結論:8.0.10を「上書きパッチ適用」するのではなく、8.0.12を入れる
質問で一番多いのがここです。
- 8.0.10を“何かの操作で”8.0.12に書き換えるという感覚ではありません。
- 8.0.12のSDK/Runtimeを(必要に応じて)別途インストールします。
ここで実務的に覚えておくと便利なのが、「SDKを入れれば、対応するRuntimeも同梱される」という点です。
- MAUI開発が目的なら、基本はRuntime単体ではなくSDKを更新します(ビルドにSDKが必要なため)。
- SDKを最新パッチへ更新すると、同じ系列のRuntime(.NET Runtime / ASP.NET Core Runtimeなど)も一緒に最新へ揃いやすくなります。
- ただしサイドバイサイド設計のため、旧Runtimeが“消える”とは限りません。残っていても異常ではありません。
また、「共存する=常に両方を使い分ける」ではありません。通常、同一系列(例:.NET 8)のアプリは、実行時に利用可能な最新パッチへ自動で繰り上がって起動します。つまり、8.0.10向けに作られたアプリでも、8.0.12が入っていれば8.0.12で動くのが一般的です(設定で特定パッチへ固定するケースもあります)。
「9.0.1が最新」と「9.0.0にパッチあり」が同時に見える理由
これも“矛盾”ではありません。例えば次の状態を想像すると理解しやすいです。
- PCに 9.0.0 と 9.0.1 が両方入っている
dotnet sdk checkは、インストール済みの各バージョンに対して「そのバージョン系列の最新パッチがあるか」を表示する
この場合、表示は自然にこうなります。
- 9.0.0 に対して:「9.0.1がある(=パッチあり)」
- 9.0.1 に対して:「最新(Up to date)」
つまり、更新状態の矛盾ではなく、複数バージョンが共存しているだけです。古い方(例:9.0.0)が不要ならアンインストールすると表示もスッキリします。
アプリは別メジャーへ自動移行しない(ここを誤解すると事故る)
.NETは便利ですが、アプリが勝手に別メジャーへ飛ぶことはありません。
- .NET 6アプリが、.NET 8や.NET 9で自動的に動くわけではありません
- サポート切れのランタイム(例:.NET 6/7など)を消す前に、そのランタイム依存のアプリが残っていないか確認が必要です
一方で、同一系列内のパッチ(例:.NET 8の 8.0.10 → 8.0.12)は、通常最新パッチへ繰り上げされます。これが「8.0.10が入っているのに、8.0.12が必要と言われる」状態の正体です。8.0.12を入れてしまえば、実行時は基本的に8.0.12へ寄ります。
dotnet workload update は「SDK本体の更新」ではない
macOSで sudo dotnet workload update を実行している場合、やっていることは主に次の更新です。
- MAUIやAndroid/iOSなど、追加機能(ワークロード)のマニフェスト更新
- ワークロードに紐づくパック(packs)やツールの更新
これはSDK/Runtimeそのものを最新パッチへ引き上げる操作ではありません。そのため、ワークロードを更新した後でも、dotnet sdk checkで「Runtimeにパッチがあります」「SDKにパッチがあります」と表示されることがあります。
| やりたいこと | 主に使う手段 | ポイント |
|---|---|---|
| .NET SDK / Runtime を新しいパッチへ上げたい | SDK/Runtimeのインストーラー(または管理ツール)で新しい版を入れる | 「上書き」ではなく「追加」。結果的に最新が使われる |
| .NET MAUIなどワークロードを最新に揃えたい | dotnet workload update | SDK更新後に再実行すると噛み合いやすい |
macOSでのおすすめ更新手順(DMG/Installer運用を想定)
macOSは「どのdotnetを使っているか」を取り違えると、更新したのに古い表示が出続けることがあります。更新前に必ず確認しておくと安全です。
どのdotnetが使われているか確認する
which dotnet
dotnet --info
dotnet --list-sdks
dotnet --list-runtimes
ここで、もしHomebrew版とインストーラー版が混在していると、PATHの順序で別のdotnetを参照してしまうことがあります。環境を安定させたいなら、インストール経路は1つに寄せるのがコツです。
必要な系列(例:.NET 8 / .NET 9)だけ最新パッチを入れる
.NET MAUIの開発では、プロジェクトのターゲットフレームワーク(例:net8.0)に対応したSDKが必要です。まずはプロジェクトファイル(.csproj)を確認します。
<PropertyGroup>
<TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks>
</PropertyGroup>
この例なら、少なくとも.NET 8系列のSDK/Runtimeは最新パッチにしておきたい、という判断になります。実務では「LTS(長期サポート)系列を主軸にし、必要に応じて次の系列も入れる」運用がトラブルが少ないです。
SDK更新後にワークロードを更新する
sudo dotnet workload update
dotnet workload list
MAUI環境では、SDK更新とワークロード更新の“順番”が効きます。SDKを入れ替えた直後は、ワークロードのマニフェストやパックが古いまま残り、ビルド時に次のようなエラーが出ることがあります。
NETSDK1147: To build this project, the following workloads must be installed: maui- テンプレート作成はできるのに、ビルドするとMAUI関連のターゲットが見つからない
- Android/iOSのビルドでパックの不整合を示すエラーが出る
こうしたときは、dotnet workload update に加えて dotnet workload repair が効くことがあります。
sudo dotnet workload repair
更新後に再チェックする
dotnet sdk check
ここで「Patch が利用可能」が残っている場合でも、“古い版が残っている”だけで、最新が入っているなら問題ないケースは多いです。不要なら後述の方法で整理できます。
Windows(Visual Studio更新)でも考え方は同じ
Windows(ParallelsのVMを含む)では、Visual Studioの更新で.NET SDKも更新されることが多いため「VSを更新したから大丈夫」と考えがちです。方向性としては正しいのですが、次の点だけ押さえると安心です。
| 更新対象 | Visual Studio更新でカバーされやすい | 追加で確認したいポイント |
|---|---|---|
| .NET SDK | 多くの場合カバーされる | CLIで使うSDKが同じとは限らないため、dotnet --infoで確認 |
| .NET Runtime | SDKに同梱される分は上がる | ランタイム単体を別経路で入れている場合は別管理になることがある |
| .NET MAUI関連(ワークロード/Android等) | VSインストーラーのワークロードで整うことが多い | dotnet workload系の状態と差が出ることがあるため、必要ならCLI側も更新 |
Visual Studioを更新した後でも、ターミナル/PowerShellで dotnet sdk check を実行すると「Patch が利用可能」が出ることがあります。その場合は、
- Visual Studioの更新がまだ反映されていない(再起動や追加コンポーネントが必要)
- 別経路で入れたSDK/Runtimeが残っている
- プロジェクトが要求するSDK系列と、VSが持っているSDK系列がズレている
といった要因が多いです。結論としては、macOSと同じで、必要な系列の最新パッチを“入れる”のが基本です。必要に応じて.NET SDK/Runtimeの単体インストーラーで補完すると早いです。
「どのSDKが使われるか」を固定したいなら global.json を使う
サイドバイサイドが便利な一方で、チーム開発やCIでは「勝手に別SDKでビルドされる」事故が起きやすくなります。特に、.NET 8と.NET 9が同居しているマシンでは、何も指定しないと新しいSDKを使ってしまい、MAUIのツールチェーンが微妙に噛み合わないことがあります。
その対策がglobal.jsonです。リポジトリ直下に置くことで、使用するSDKを固定できます。
{
"sdk": {
"version": "8.0.xxx",
"rollForward": "latestPatch"
}
}
ここで重要なのは次の2点です。
- version に合わせたSDKがインストールされていないと、ビルド自体が失敗する
- rollForward を適切に設定すれば、同一系列の最新パッチへ繰り上げできる(固定しすぎない)
「社内PCはバラバラ」「macOSとWindowsが混在」「ParallelsのVMもある」ような環境ほど、global.jsonで足並みを揃えるとトラブル対応コストが下がります。
不要なSDK/Runtimeを整理して表示をスッキリさせる
サイドバイサイド運用では、放っておくとSDK/Runtimeが増えていき、dotnet sdk checkの表示が騒がしくなります。実務での整理方針はシンプルです。
- 普段ビルドするターゲット(例:net8.0)に必要な系列は残す
- 同一系列の古いパッチは、必要性がなければ消してよい
- サポート切れの系列(使っていないなら)を消すとトラブルが減る
| 状況 | 残す判断 | 消す判断 |
|---|---|---|
| MAUIプロジェクトがnet8.0で運用中 | .NET 8の最新パッチ(SDK/Runtime) | .NET 8の古いパッチ(動作確認済みなら) |
| 過去にnet6.0で作ったツールがまだある | そのツールが依存する.NET 6 Runtime | ツール側をアップグレードできたら.NET 6を削除 |
| .NET 9は試験的に触っただけ | 今後も検証するなら残す | 触らないなら削除して混乱を減らす |
削除前には必ず次を実行し、実際に使っている系列を把握します。
dotnet --list-sdks
dotnet --list-runtimes
古いランタイムを削除すると、依存しているアプリが起動できなくなることがあります。特に「グローバルツール(dotnet tool)」や「過去に入れた小さなユーティリティ」は気付きにくいので、削除後に困らない順序で整理すると安全です。
よくあるトラブルと切り分け(macOS/Windows共通)
インストールしたのに古いdotnetが動いている
which dotnet(Windowsならwhere dotnet)で参照先を確認- 複数経路(インストーラー、Homebrew、VS同梱など)を混在させない
- ターミナルを開き直してPATH反映を確認
dotnet workload update が権限エラーになる
- macOSでインストーラー版を使っている場合、
sudoが必要になることがある - それでも失敗するなら
dotnet workload repairを試す - 過去にsudo実行と通常実行が混在していると、ファイルの所有者がズレて不具合が出ることがある
Patchが利用可能が消えない
- 古い版が残っているだけの場合が多い(最新が入っていれば“動作”は問題ないことが多い)
- 表示を消したいなら、不要な旧版をアンインストールして整理する
.NET MAUI開発者向けの実務的な運用ルール
最後に、macOSとWindows(VM含む)を行き来するMAUI開発で安定しやすい運用ルールをまとめます。
- プロジェクトが必要とする系列(例:.NET 8)を決め、そこだけは常に最新パッチにする
- SDK更新後は必ずワークロード更新(
dotnet workload update)をセットで行う - global.jsonでSDKを固定し、チームやCIの差分を減らす
- 検証用の系列(例:.NET 9)を入れるなら、用途を決めて放置しない
- 不要な旧版は定期的に整理し、
dotnet sdk checkの警告を“本当に必要な警告”に戻す
dotnet sdk checkの「Patch が利用可能」と「Up to date」は、.NETの設計を理解すると“正常な表示”です。必要な系列の最新版を入れて、ワークロードも揃え、不要な版を整理する。この3点を回すだけで、macOSでもWindowsでもMAUI環境はかなり安定します。

コメント