.NET Runtime 9 アンインストール後にレジストリが残る理由と安全な削除手順(Windows対応)

Windows に .NET Runtime 9.0.2 をインストールしたあと、コントロール パネル(または「アプリと機能」)からアンインストールしても、レジストリに関連キーが残ってしまうことがあります。この記事では「なぜ残るのか」「削除するならどこを消すべきか」「自動クリーンアップは可能か」「仕様か不具合か」を、実務で迷わない手順として整理します。

目次

.NET Runtime 9 をアンインストールしてもレジストリが残る現象とは

.NET Runtime 9.0.2 を入れると、Windows のレジストリに .NET のインストール情報(バージョン、インストール先、ホスト関連の情報など)が記録されます。ところがアンインストール後も、その情報が“完全には”消えないことがあります。

この状態は、環境によっては「痕跡が残って気持ち悪い」程度で済みますが、次のようなケースでは実害に見えることがあります。

  • 社内スクリプトや監視ツールが「レジストリだけ」を見て .NET の有無を判定しており、誤検知する
  • 別のインストーラーが「レジストリ上にある=入っている」と誤解して前提チェックをすり抜ける/逆に失敗する
  • 検証用 PC で「完全にクリーンな状態」を作りたい(再現性のあるテストがしたい)

結論:アンインストールしてもレジストリ キーが消えないのは“現状の挙動”として起こり得る

今回のポイントはここです。現時点では .NET Runtime をアンインストールしても、対応するレジストリ キーが自動でクリーンアップされないことがあるため、レジストリ上の痕跡が残るのは必ずしも異常ではありません。

「アンインストール=痕跡ゼロ」を期待すると違和感がありますが、Windows と .NET の構造上、インストーラーが“安全側”に倒して、削除し切らない設計になっていても不思議ではありません。

なぜ自動で消えないのか:よくある設計理由

Q&A の回答では明確な公式理由が提示されていない前提ですが、実務的に見て「自動で消し切らない」方向に寄りがちな理由は複数あります。ここを理解しておくと、削除判断がブレません。

共有コンポーネントと参照の問題(Side-by-side / 共有ホスト)

.NET は複数バージョンの共存(Side-by-side)が前提です。さらに host / hostfxr / shared framework など、仕組みとして“共有されやすい部品”があります。アンインストーラーが「このキーは今誰も参照していない」と確実に言い切れない場合、消さない方が安全になります。

将来の修復やアップグレードの判定に使う可能性

インストーラーがレジストリを完全に消すと、修復(Repair)や差分更新、後続インストールの判定で困るケースが出ます。特に “インストールされていた履歴” を参照して動く仕組みがあると、痕跡を残す方が運用上ラクな場合があります。

「削除し過ぎると壊れる」リスクを避ける安全設計

レジストリは OS 全体の設定データベースです。削除対象の見極めが難しいキー(他製品や別コンポーネントが見ている可能性があるキー)を自動削除するのは、製品側としてリスクが高くなります。結果として「不要でも残す」設計になりやすい領域です。

グローバル ツールやワークロードなど“別枠”の要素が混在しやすい

.NET では、SDK、Runtime、ASP.NET Core Runtime、Desktop Runtime、ワークロード、グローバル ツールなどが絡み合います。アンインストール対象が Runtime だけであっても、関連キーを一律に消すと別枠の要素に影響する可能性があり、結果として「完全削除はしない」挙動になってもおかしくありません。

仕様なのか不具合なのか:判断の考え方

ユーザー視点では「アンインストールしたのに残る=バグでは?」となりがちですが、ソフトウェアの世界では次のように整理すると納得しやすいです。

観点仕様(設計)寄り不具合(バグ)寄り
レジストリが残っていても実害がない残しても問題ないメタデータとして扱っている可能性—
レジストリが残るせいで誤検知やインストール失敗が起きる—インストール判定を壊す“残骸”になっている可能性
別バージョンや別コンポーネントと共存している共有・共存を優先して消さない方針の可能性消すべきバージョンだけ残っているなら改善余地
削除対象が曖昧(どこまでが Runtime なのか)安全側で残すのは自然—

今回の Q&A では「残るのは現状の挙動(仕様として起こり得る)」という整理でした。ただし、レジストリ残骸が原因で具体的な不具合が起きるなら、改善要望として .NET チームに報告する価値があります。

まず確認:本当に「残骸」か、それとも他の .NET が参照しているのか

削除に入る前に、次の確認をしてください。ここを飛ばすと「消してはいけないもの」を消す確率が上がります。

確認1:.NET が実際に残っていないか(コマンド)

管理者権限が不要な範囲で、まずは .NET の状況を見ます。

dotnet --info
dotnet --list-runtimes
dotnet --list-sdks

ここで .NET 9.0.2 が一覧に出ないのに、レジストリだけ残っているなら「残骸」可能性が高くなります。逆に一覧に出るなら、どこかに実体が残っているか、別コンポーネントとしてまだ必要な状態の可能性があります。

確認2:インストール先フォルダの有無

代表的には次の配下に実体が置かれます(環境で異なる場合があります)。

  • C:\Program Files\dotnet\
  • C:\Program Files (x86)\dotnet\

該当バージョンのフォルダ(例:shared framework のバージョンフォルダ)が残っていないか確認します。レジストリだけが残っているのか、ファイルも残っているのかで、取るべき対応が変わります。

確認3:同居している .NET バージョンがないか

特に開発機や検証機は .NET 6/7/8/9 が混在しがちです。“9.0.2 だけ消したい”のに、ルートのキーや共通キーをごっそり消すと、他バージョンまで巻き込みます。

手動で削除する場合:どのエントリを削除すべきか

質問で出ている「3つの行すべてか、Version だけか」という迷いに対して、実務的におすすめの考え方は次の通りです。

原則:値(Versionだけ)ではなく、“該当バージョンのキー単位”で消す方が安全

レジストリの値だけを部分的に消すと、キー構造が中途半端に残り、逆に判定ロジックを壊すことがあります。クリーンアップ目的なら、該当バージョンを表すサブキーを丸ごと削除する方が、結果として整合性が取りやすいです。

ただし、削除対象は「.NET 9.0.2 の Runtime に対応する“バージョンの枝”」に限定し、ルートに近い共通キーは避けます。

よく見かける場所:.NET の Setup / InstalledVersions 系

.NET のインストール情報は、環境によって差はあるものの、概ね “InstalledVersions” や “sharedfx / hostfxr / sharedhost” といった単語を含む階層に集まります。典型的には 64bit / 32bit(x64 / x86)で枝が分かれます。

ここで大事なのは、「9.0.2 の枝だけ」を狙うことです。以下の表は、作業時の判断に使うための“削除可否の目安”です(実際のパスや名称は環境差があります)。

見え方(例)意味削除してよい条件削除しない方がよい条件
InstalledVersions 配下の「9.0.2」サブキー特定バージョンが入っていた記録やインストール先dotnet –list-runtimes に 9.0.2 が出ない/フォルダも存在しない9.0.2 が実際に残っている、または別の .NET 9 系が共存しており判定に使われている
sharedfx 配下の特定バージョン共有フレームワーク(Microsoft.NETCore.App 等)のバージョン情報該当フレームワークの 9.0.2 が不要であることが確認できる別製品がその sharedfx を参照して動いている(業務アプリなど)
hostfxr 配下の特定バージョン.NET アプリ起動時のホスト関連(ホストの解決に関わる)dotnet が正常動作し、9.0.2 の hostfxr が不要と判断できる削除後に dotnet コマンドやアプリ起動が壊れるリスクを避けたい
sharedhost など共通っぽいキー(バージョンが限定されない)複数バージョンや他コンポーネントが共有して参照する可能性基本的には“触らない”のが無難他バージョンまで巻き込むリスクが高い

「3つの行」は全部消すべき?

対象が「9.0.2 を表すバージョン専用のキー配下」であり、そこに Version 以外にも値が並んでいるなら、クリーンアップ目的では そのキー配下をまとめて削除するのが分かりやすいです。値だけを残す・消すの判断をすると、後から見たときに“何が正しい状態か”が分からなくなります。

逆に、バージョンに紐づかない共通キーに「3つの行」がある場合は、そこは他コンポーネントも見る可能性があるため、安易に削除しない方が安全です。

レジストリ削除の安全手順(バックアップ必須)

レジストリ操作は失敗すると影響が大きくなります。必ず次の順で行ってください。

作業前チェックリスト

  • 現在の .NET 状況を記録(dotnet --info / dotnet --list-runtimes)
  • .NET 9.0.2 の実体フォルダが残っていないか確認
  • 削除予定のキーが「9.0.2 に限定されている」ことを確認
  • 復元手段を確保(レジストリのエクスポート、可能なら復元ポイント)

手順1:レジストリ キーをエクスポートしてバックアップ

Windows の regedit(レジストリ エディター)で、削除予定のキーを右クリックして「エクスポート」を実行し、.reg ファイルとして保存します。これが最低限の保険です。

万一問題が出たら、その .reg をダブルクリックして取り込むことで元に戻せる可能性があります(環境や権限により完全復元できない場合もあるため、慎重に扱ってください)。

手順2:該当バージョン(9.0.2)の“枝”を削除

削除は「値」ではなく「9.0.2 を表すサブキー」を中心に行います。削除後は一度 OS を再起動するか、少なくとも対象アプリ/サービスを再起動して状態を確認します。

手順3:削除後に再確認

次の観点で確認します。

  • dotnet --list-runtimes に 9.0.2 が出ない(=狙い通り)
  • 必要な .NET アプリが起動できる(=巻き込み事故がない)
  • 社内ツールやインストーラーの判定が改善する(=レジストリ残骸が原因だった)

PowerShell で“確認”を効率化する(削除の自動化は慎重に)

レジストリ削除を完全自動化するのはリスクがあるため、まずは PowerShell で「存在確認」「バックアップ」「対象の絞り込み」を効率化するのがおすすめです。

.NET の実体確認(まずはコマンド出力を信頼する)

dotnet --list-runtimes
dotnet --list-sdks

レジストリの探索をする場合の考え方

探索は “dotnet” や “InstalledVersions” などの語で当たりを付け、見つけたキーが本当に 9.0.2 固有かを目視で確認してからにします。企業環境やサーバーでは、削除スクリプトをいきなり配布しない方が安全です。

自動でクリーンアップできるレジストリ ツールはある?

結論から言うと、「これを使えば安全に .NET の残骸だけ消せる」という万能ツールは期待しない方がよいです。理由は単純で、レジストリの“不要”を完全自動で判定するのが本質的に難しいからです。

レジストリ クリーナーの注意点(使うなら理解してから)

  • 誤検知で必要なキーまで削除し、アプリが壊れるリスクがある
  • 削除内容がブラックボックス化しやすく、原因切り分けが困難になる
  • 企業環境では利用ポリシーや監査的にNGになりやすい

どうしても使う場合でも、少なくとも「削除候補の一覧を提示して、ユーザーが選べる」「復元機能がある」「ログが残る」タイプに限定し、事前バックアップを徹底してください。

現実的におすすめの“自動化寄り”アプローチ

「レジストリ クリーナーで全部お任せ」より、次の方が安全で再現性があります。

  • アンインストール手段を統一する(GUI、winget、管理ツールなどを混ぜない)
  • dotnet コマンドの結果を正として、検知ロジックをレジストリ依存から外す(社内スクリプトの改善)
  • 検証環境はスナップショットや VM で作り直す(完全クリーンを短時間で作れる)

「残っても気にしない」が正解になるケース

レジストリの数行程度の残骸は、ディスク容量やパフォーマンスに影響することは通常ほぼありません。次に当てはまるなら、無理に削除しないのも立派な選択です。

  • PC は個人利用で、.NET の検証をたまにする程度
  • アプリの動作に問題がなく、誤検知も起きていない
  • 今後も .NET の別バージョンを入れる予定があり、共存が前提

「気持ち悪さ」だけで削除に踏み切ると、復旧コストの方が高くつくことがあります。

逆に、クリーンアップした方がよいケース

一方で、次の状況では削除を検討する価値があります。

  • レジストリ参照の検知が原因で作業が止まっている(インストーラーが誤判定する、監視が誤検知する)
  • 検証の再現性が重要で、環境差を極小化したい(CI用PC、QA用の再現環境など)
  • 「入っていないこと」を証明する必要がある(監査、棚卸し、社内申請)

この場合も「消す=正義」ではなく、影響範囲を限定して、バックアップを取って、段階的にが鉄則です。

.NET チームに確認したい場合:GitHub の Issue を活用する

「なぜアンインストールで消えないのか」「消すべきか残すべきか」を設計意図として納得したいなら、最終的には .NET 開発チームに確認するのが一番確実です。GitHub の dotnet/runtime リポジトリで同様の Issue がないか検索し、なければ新規に投稿して状況を共有するのが現実的です。

Issue を出すときは、次の情報があると話が早くなります。

  • OS(Windows 10 / Windows 11 / Windows Server の版とビルド)
  • インストールした .NET Runtime の種類(Runtime / ASP.NET Core Runtime / Desktop Runtime)とバージョン
  • アンインストール手順(コントロール パネル、設定アプリ、winget 等)
  • アンインストール後に残るキーの場所(可能ならスクリーンショットやパス)
  • 実害の有無(誤検知、インストール失敗などの具体例)

実務で迷わないための最終まとめ

やりたいことおすすめ手段理由
とにかく安全に運用したいレジストリは触らず、dotnet の実体とコマンド出力で管理巻き込み事故が起きにくい
検証環境をクリーンに戻したいVM/スナップショットで戻す、または 9.0.2 固有キーのみ手動削除再現性が高く、リスクを局所化できる
誤検知を止めたいレジストリ依存の検知を見直す/必要なら残骸キーだけ削除根本原因の解消になる
仕様として納得したいdotnet/runtime で Issue 検索・投稿公式見解が得られる可能性がある

要点はシンプルです。アンインストール後にレジストリが残るのは起こり得る挙動であり、放置しても問題ないことが多い一方、誤検知などの実害があるなら 「9.0.2 固有の枝だけ」をバックアップ付きで削除するのが現実的です。自動クリーンアップは魅力的ですが、レジストリ領域は“便利さより安全”を優先した方が、結果として早く解決します。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次