NuGetの更新中に、非推奨の「Microsoft.Bcl 1.1.10」が混ざっていて脆弱性警告が消えない──そんな状況は珍しくありません。.NET Framework 4.8でも、古いWeb API系パッケージや旧PCLへの依存が残っているとBclが引き込まれます。この記事では、依存元の特定から安全にBclを不要にする更新・削除手順までを具体的に解説します。
Microsoft.Bclとは何か:.NET Framework 4.8なのに入ってくる理由
Microsoft.Bclは、かつての.NET環境で不足していたAPIや型(および互換性の差)を埋めるための互換レイヤーとして配布されていたNuGetパッケージです。歴史的には「新しいBCL(Base Class Library)の一部を、古いターゲットでも扱えるようにする」目的で使われました。
ややこしいのは、あなたのアプリが.NET Framework 4.8をターゲットにしていても、参照しているNuGetパッケージ側がnet45のみ対応、または旧PCL(portable-*)前提のままだと、その“ギャップ”を埋めるためにBclが依存関係として引き込まれる点です。
Microsoft.Bcl.Buildも一緒に入るのはなぜ?
Microsoft.Bclとセットで入ることが多いMicrosoft.Bcl.Buildは、ビルド時に参照やターゲットを差し込むための仕組み(targets)を提供します。古いプロジェクト形式では.csprojに<Import>が追加され、そこが残骸として残ると「アンインストールしたのにエラーが出る」状態になりがちです。
「アプリが新しい=依存も新しい」ではない
NuGetは参照しているパッケージが要求する依存関係を解決します。つまり、アプリ側が4.8でも、依存先が古い設計のままだと、その古さを成立させる互換パッケージが入り込みます。Web API(ASP.NET Web API 2)系の古い版や、旧PCLを前提にしたライブラリで起きやすい典型パターンです。
なぜ今「脆弱性あり」警告として目立つのか
Visual Studio / NuGetは、既知のアドバイザリ情報に基づいて「脆弱性のあるパッケージが含まれています」という警告を表示します。ここで重要なのは、警告の対象はあなたが直接入れたパッケージだけではなく、依存関係で引き込まれた間接(トランジティブ)依存も含まれる点です。結果として、Bclを手動で消そうとしても、依存元が残っていれば再び復元されます。
| よくある症状 | 典型的な原因 | 最短の解決方針 |
|---|---|---|
| Microsoft.Bcl 1.1.10が非推奨・脆弱性警告 | 古いnet45/portable-*前提のNuGetが依存している | 依存元パッケージをBcl不要な新しい版へ更新 |
| Bclをアンインストールするとビルドエラー | 依存元がまだBclを要求している(依存解決が崩れる) | 先に依存元の更新・置換、最後にBcl削除 |
| ソリューションの一部だけにBclが入る | 4.5系など古いターゲットが混在/特定プロジェクトだけ旧PCL依存 | ターゲットフレームワークの統一+“犯人プロジェクト”の特定 |
最初にやるべきこと:依存関係を「見える化」して犯人を確定する
Microsoft.Bclを“使わない状態”にするには、まずどのパッケージがBclを要求しているのかを特定する必要があります。ここを曖昧にすると、アップデートの方向性を間違えて時間を溶かします。
確認ポイント(プロジェクトとNuGetの状態)
| 確認項目 | 見る場所 | 目的 |
|---|---|---|
| ターゲットフレームワーク | プロジェクトのプロパティ(アプリケーション) | 4.5系が混在していないか、4.6+に統一できるか判断 |
| NuGet管理方式 | packages.config か PackageReference か | 依存関係の見え方・更新手順が変わる |
| Bclの導入経路 | インストール済み一覧/依存関係ツリー | 「直接」か「依存(間接)」かを切り分ける |
Package Manager Consoleで一覧化する(packages.configでも有効)
Visual Studioのパッケージ マネージャー コンソールで、まず現在の状況を一覧化します。
Get-Package
ここにMicrosoft.BclやMicrosoft.Bcl.Buildが出てきたら、次に「同時に入っているパッケージ」を見ます。Web API系(Microsoft.AspNet.WebApi.Client / Microsoft.AspNet.WebApi.Core)や、HTTP系(Microsoft.Net.Http)が候補になりやすいです。
どのプロジェクトがBclを引き込んでいるかを一発で探す
ソリューションが大きいと「どのプロジェクトが犯人か」が分からなくなりがちです。次のように文字列検索で当たりを付けると早いです。
例:Bclの参照が残っているcsprojを探す(PowerShell)
# ソリューション配下で "Microsoft.Bcl" を含むプロジェクトファイルを探す
Get-ChildItem -Recurse -Filter *.csproj | Select-String "Microsoft.Bcl"
例:packages.configからBclを参照しているプロジェクトを探す(PowerShell)
Get-ChildItem -Recurse -Filter packages.config | Select-String "Microsoft.Bcl"
PackageReferenceの場合:トランジティブ依存も含めて確認する
SDKスタイル(PackageReference)に移行済み、または一部プロジェクトだけ移行している場合は、dotnetコマンドで依存を見える化できます。
dotnet list package --include-transitive
表示結果にMicrosoft.Bclがいる場合、「どのパッケージ経由で入っているか」を追跡し、更新候補を絞り込みます。
結論:Microsoft.Bclだけを外したいなら「依存元」をアップデートする
多くのケースで、Bclはあなたが“使いたくて入れた”のではなく、古いパッケージが要求しているから入っているだけです。したがって、Bclを外す最短ルートは次のどちらかになります。
- 依存元パッケージを、Bcl不要なバージョンへ更新する
- 依存元パッケージを置き換える(または削除する)
代表的な依存元と、更新方針の目安
| 依存元になりがちなパッケージ | おすすめの方針 | 補足 |
|---|---|---|
Microsoft.AspNet.WebApi.Client | 5.2.5以上など、Bcl不要な世代へ更新 | 古い4.x系はnet45のみ対応でBcl依存が残りやすい |
Microsoft.AspNet.WebApi.Core / Microsoft.AspNet.WebApi.WebHost | Web API 2系でバージョンを揃えて更新 | Clientだけ上げるとバージョン不整合で別の警告が出ることがある |
Microsoft.Net.Http | 可能なら依存を外し、System.Net.Http(フレームワーク標準)へ寄せる | .NET Framework 4.8なら原則こちらで足りる |
旧PCL(portable-*)のみのサードパーティ | アップデート版の有無を確認し、なければ代替を検討 | ここが残るとBcl依存から逃れにくい |
実践手順:安全にBclを外すための更新・削除フロー
ここからは、現場で事故らないために「やる順番」を固定して進めます。いきなりBclを消しにいくのではなく、依存元→最後にBclの順にしてください。
手順1:ソリューション内のターゲットフレームワークを揃える
まず、ソリューション内に4.5/4.5.1/4.5.2などが混在していないか確認します。混在している場合は、可能な範囲で.NET Framework 4.6以上(推奨4.8)へ統一します。ここが揃わないと、あるプロジェクトのためにBclが残り続けることがあります。
手順2:依存元(Web API / HTTP系)をBcl不要な世代へ上げる
依存元の候補がWeb API系なら、バージョンの揃え方が重要です。部分更新だと参照関係がねじれて別の問題が出るため、基本は関連パッケージを同一系列でまとめて更新します。
パッケージ マネージャー コンソールから更新する例:
# 例:Web API 2系をまとめて更新(バージョンはプロジェクトに合わせて調整)
Update-Package Microsoft.AspNet.WebApi.Client
Update-Package Microsoft.AspNet.WebApi.Core
Update-Package Microsoft.AspNet.WebApi.WebHost
特定バージョンへ固定して上げたい場合(例として5.2.5以上へ):
Update-Package Microsoft.AspNet.WebApi.Client -Version 5.2.5
Update-Package Microsoft.AspNet.WebApi.Core -Version 5.2.5
更新後は一度ビルドして、Microsoft.Bclが依存関係から外れているかを確認します。外れていない場合は、まだ別の依存元が残っている可能性が高いので、前の「見える化」手順に戻って原因を潰します。
手順3:Microsoft.Bcl / Microsoft.Bcl.Build をアンインストールする
依存元の更新ができたら、ようやくBclの削除に入ります。通常は次の順で問題ありません。
Uninstall-Package Microsoft.Bcl
Uninstall-Package Microsoft.Bcl.Build
手順4:削除後の確認ポイント(ビルドが通っても油断しない)
「ビルドが通った=完全に安全」とは限りません。Bclが絡む領域は、実行時に差が出ることもあるため、次の観点で確認すると安心です。
- 出力フォルダ(bin)に
Microsoft.Bcl.dllなどが残っていないか - HTTP通信(HttpClient)を使う箇所が本番相当の設定で動くか
- シリアライズ(JSON/XML)やTLS設定など、環境差が出やすい箇所を回帰テスト
手順5:まだ参照が残るときは、packages.config と csproj をクリーンアップする
古いプロジェクト(特にpackages.config運用)では、削除しても.csprojにImportが残っていたり、packages.configに記述が残っていたりして、復元時に不整合が起きることがあります。ビルドエラーが出る場合は、次のポイントを確認します。
packages.configからBcl関連の行を削除(例):
<package id="Microsoft.Bcl" version="1.1.10" targetFramework="net461" />
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net461" />
.csprojからBcl.BuildのImportやターゲットを削除(例):
<Import Project="..\\packages\\Microsoft.Bcl.Build.1.0.14\\tools\\Microsoft.Bcl.Build.targets"
Condition="Exists('..\\packages\\Microsoft.Bcl.Build.1.0.14\\tools\\Microsoft.Bcl.Build.targets')" />
この作業はあくまで「掃除」です。依存元がまだBclを要求している状態で無理に消すと、ビルドが落ちる/実行時に欠落する可能性が高いので、必ず先に依存元の更新を終えてから行ってください。
それでもBclが消えないときの原因チェックリスト
更新・削除を正しくやってもBclが残るケースがあります。多くは「どこかに古い前提が残っている」だけなので、次のチェックで潰していくと解決が早まります。
| チェック項目 | 確認方法 | 対処の方向性 |
|---|---|---|
別プロジェクトがnet45をターゲットにしていないか | ソリューション内の全プロジェクトのプロパティを確認 | 可能なら4.6+へ統一。難しいなら“残る理由”を明確化 |
旧PCL(portable-*)の依存が残っていないか | NuGetパッケージの対象TFMを確認(パッケージのlib配下など) | アップデート版/代替ライブラリの検討 |
| Web API関連のバージョンが揃っていない | Get-PackageでWebApi.*のバージョンを横並びで確認 | 同一系列(例:5.2.x)で統一 |
Microsoft.Net.Httpが残っている | インストール済み一覧を確認 | .NET 4.8なら標準System.Net.Httpへ寄せる |
| 手動編集の残骸がある | csprojのImport/Target、packages.configの行、packagesフォルダの残骸 | 不要な記述を削除→NuGet復元→リビルド |
packagesフォルダを一度リセットして復元する(packages.config運用の定番)
packages.config運用で依存が絡まっている場合、packagesフォルダに古いdllが残って挙動がぶれることがあります。次の順で一度リセットすると、意外とあっさり解決することがあります。
- ソリューションを閉じる
packagesフォルダを削除(または退避)- Visual Studioでソリューションを開き、NuGet復元(ビルド)を実行
ただし、チーム開発では「誰の環境でも再現する状態」になっているか(CIで通るか)を必ず確認してください。
packages.configからPackageReferenceへ移行すると改善しやすい理由
可能であれば、packages.configからPackageReferenceへ移行すると、依存関係の可視化・更新・固定がやりやすくなります。Bclのような“間接依存の混入”に気づきやすいのもメリットです。
| 観点 | packages.config | PackageReference |
|---|---|---|
| 依存関係の見え方 | 間接依存が見えにくい | トランジティブ依存を確認しやすい |
| プロジェクトファイルの汚れ | Import/targetsが残りやすい | csprojが比較的シンプル |
| 一括更新 | プロジェクトごとに差が出やすい | 統一しやすい(バージョン管理が楽) |
移行自体は別テーマですが、Bclのような「古いビルドターゲットの残骸」に悩まされている場合、長期的には移行が効いてきます。
どうしても古いライブラリを外せない場合の落とし所
サードパーティのライブラリがnet45のみ対応で、アップデートも代替もない場合、Bcl依存が残るのはある意味で自然です。この場合は「警告を消す」ことだけに固執すると、逆に危険な対応(強制削除)になりがちです。
優先順位を整理する(おすすめの判断軸)
- 最優先:依存元ライブラリの更新・置換でBclを排除できないか
- 次点:当該ライブラリの利用範囲を縮小できないか(機能の切り出し、別モジュール化など)
- 最後:警告の抑制(ビルドを通すための一時措置)
警告だけを抑制する方法(おすすめはしないが知っておく)
短期的にビルドを通す必要がある場合、NuGetの脆弱性警告(例:NU1901〜NU1904)を抑制する設定があります。ただし、これは“リスクを見ないふりをする”手段なので、必ず期限と代替策をセットで運用してください。
例:プロジェクトファイルにNoWarnを追加(PackageReferenceの場合)
<PropertyGroup>
<NoWarn>$(NoWarn);NU1901;NU1902;NU1903;NU1904</NoWarn>
</PropertyGroup>
根本解決は依存元を更新してBclが不要な構成にすることです。抑制は“緊急避難”として扱いましょう。
再発防止:同じ依存問題に戻らないための運用
一度Bclを外せても、別の開発者が古いパッケージを追加したり、依存の固定が崩れたりすると再発します。運用で防ぐと、将来の保守コストが確実に下がります。
バージョンを「揃える」ルールを作る
Web APIのように関連パッケージが複数あるものは、バージョンがズレると依存解決が不安定になります。次のようなルールを明文化しておくと、チーム全体で事故が減ります。
- Web API関連(WebApi.Client/Core/WebHostなど)は同一系列のバージョンで統一する
- ソリューション内で.NET Frameworkのバージョンを原則統一する
- 旧PCLのみ対応のパッケージは新規採用しない(代替を探す)
更新前に「どのTFMを持っているパッケージか」を見る癖を付ける
パッケージがnet45しか持っていないのか、net46やnetstandard2.0を持っているのかで、将来の互換性と保守性は大きく変わります。導入前に対象フレームワーク(TFM)を確認するだけでも、Bclのような互換パッケージに引っ張られる確率は下がります。
まとめ:Bclを消す最短ルートは「依存元の近代化」
Microsoft.Bclは、あなたの.NET Framework 4.8アプリに必須だから入っているのではなく、古い依存を成立させるために入っているケースが大半です。警告を安全に消したいなら、次の流れが鉄板です。
- ソリューション全体のターゲットフレームワークを4.6+(推奨4.8)に統一する
- Web API / HTTP系など、Bclを要求しがちな依存元パッケージをBcl不要な世代へ更新する
- 最後に
Microsoft.Bcl/Microsoft.Bcl.Buildをアンインストールし、設定残骸をクリーンアップする
この順番を守れば、「他のパッケージは削除したくない」という要件を満たしつつ、非推奨パッケージと脆弱性警告の原因を根本から取り除けます。

コメント