Microsoft.Build.CentralPackageVersions で NuGet パッケージのバージョンを一元管理する


前置き

仕事で勉強中のとあるソリューションのサンプルプロジェクトで、
Microsoft.Build.CentralPackageVersions というツールが使われていました。

Microsoft.Build.CentralPackageVersions を使用することによって、
ソリューション内のプロジェクトで使用する NuGet パッケージのバージョンを一元管理することが出来ます。

Microsoft.Build.CentralPackageVersions は MSBuild Project SDKs と呼ばれるビルドの構成と拡張に使用されるSDKの1つです。

Qiita には Microsoft.Build.CentralPackageVersions に関する記事は存在しなかったようなので、
今回簡単に使い方を紹介してみたいと思います。

使い方例

  • 環境
    • Visual Studio Professional 2019 verasion 16.11.7
    • .NET Framework 4.8

サンプルプロジェクトを作成してみます。
1つのソリューション配下に2つのプロジェクトが存在する例とします。

まずソリューションアイテムに Directory.Build.Targets という名前のファイルを作成し、
以下の内容を記述します。

<Project>
  <Sdk Name="Microsoft.Build.CentralPackageVersions" Version="2.1.3" />
</Project>

Directory.Build.Targets により、各プロジェクト内の プロジェクトプロパティ値を共通化できます。
Directory.Build.Targets に前述の内容を記述することにより、
「Microsoft.Build.CentralPackageVersions」を全プロジェクトで使用する、という設定にすることができます。
(※ 正確には Directory.Build.Targets の対象範囲はソリューションとは無関係なのでご注意を

この時点でソリューションをビルドしてみます。
ユーザーフォルダ内の .nuget フォルダに Microsoft.Build.CentralPackageVersions のパッケージがダウンロードされていることがわかります。
C:\Users\<yourusername>\.nuget\packages\microsoft.build.centralpackageversions
(この辺りの仕組みはこちらのブログ内の「Project SDK resolution」での解説がわかりやすかったです)

続いてプロジェクトで使用する NuGet パッケージをインストールします。
パッケージをダウンロードする前に、NuGet のパッケージ管理形式を「PackageReference」にする必要があります。

Visual Studio の「ツール > オプション > Nugetパッケージマネージャー > 既定のパッケージ管理形式」を PackageReference にするか、「パッケージの初回インストール時に形式の選択を許可する」をONにします。

ソリューションファイルを右クリックし「ソリューションの NuGet パッケージの管理」からパッケージをインストールします。
もしこの時点でエラーウィンドウにエラーが表示されてインストールが開始されなかったら、一度ソリューションを閉じて Visual Studio を再起動してみてから再度インストールを試してみてください。

PackageReference 形式でインストールしたパッケージは、アイコンが NuGet マークになっています。

続いてソリューションアイテムに Packages.props という名前のファイルを作成し、以下の内容を記述します。

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <PackageReference Update="Newtonsoft.Json" Version="12.0.3" />
  </ItemGroup>
</Project>

ここでソリューションをビルドしてみると、以下のようなエラーが発生するはずです。

The package reference 'Newtonsoft.Json' should not specify a version.  
Please specify the version in 'C:\Users\<yourusername>\source\repos\CentrallyPackageManage\Packages.props' or set VersionOverride to override the centrally defined version.    
Project2    C:\Users\<yourusername>\source\repos\CentrallyPackageManage\Project2\Project2\Project2.csproj       

csproj ファイルにパッケージのバージョン番号が書かれていてるが、
Microsoft.Build.CentralPackageVersions により
Packages.props に記載しているバージョン番号が優先される旨がエラーとして表示されます。

Packages.props ファイルに記載していないパッケージをソリューション配下のいずれかのプロジェクトでインストールした後にビルドすると、同様のエラーが発生します。
新しいパッケージを採用する際は、Packages.props に記述する必要があります。
Packages.props に記述しているパッケージをプロジェクトで使用しない場合は、ビルドエラーは発生しません。

エラーを解消するには、.csproj ファイル内でパッケージのバージョン番号を指定している箇所を削除します。

<ItemGroup>
    <PackageReference Include="Newtonsoft.Json">
      **** <Version>12.0.3</Version> *** ←削除する
    </PackageReference>
</ItemGroup>

ソリューションエクスプローラーでプロジェクトファイルを右クリックし「プロジェクトのアンロード」を行って .csproj ファイルを直接編集します。
編集が完了したらプロジェクトファイルを右クリックし「プロジェクトの再読み込み」を行い、戻します。

特定のプロジェクトだけ異なるバージョンのパッケージを使用したい場合

何らかの理由で特定のプロジェクトだけ異なるバージョンのパッケージを使用したい場合は、以下のように対象のプロジェクトの .csproj ファイル内で VersionOverride を記述し、バージョン番号を指定することが可能です。

<ItemGroup>
    <PackageReference Include="Newtonsoft.Json" VersionOverride="13.0.1">
    </PackageReference>
</ItemGroup>