sh1’s diary

プログラミング、読んだ本、資格試験、ゲームとか私を記録するところ

.NET プログラムのバージョンを管理する例

.NET でアプリケーションを作成したとき、プログラムのバージョンを正しく管理し続けることが難しいプロジェクトが結構あると思います。.NET の場合は、すくなくとも以下の3つのバージョンを管理する必要があります。

  • バージョン(パッケージバージョン) version
  • アセンブリバージョン assembly version
  • ファイルバージョン file version

バージョンの記述方法の基本は、「アセンブリのバージョン番号」にあるので、割愛。

  • メジャーバージョン
  • マイナーバージョン
  • ビルド番号
  • リビジョン

バージョンの基本的な用途のポイント

もっとも基本的なバージョンは、「ファイルバージョン」です。ユーザーがインストールされているプログラムのバージョンを確認したりするときの数字はファイルバージョンを参考にします。

つぎに、「アセンブリバージョン」は CLR (Common Language Runtime) がプログラムを識別するために使用されるようです。

最後に、パッケージバージョンは「NuGet」でのバージョンとして参照されることになります。

現実的に、2007年ごろの開発では NuGet を使用していない環境が当たり前だったので ITMedia では「ファイルバージョンとアセンブリバージョンを同じにしてしまう」といった手法が紹介されており、この説明として「しかし現実的には、このアセンブリ・バージョンとファイル・バージョンを1つにまとめて設定できた方が、バージョン番号の管理は容易になるだろう。」というような一文もありました。

現在はどういったバージョン管理がよいでしょうか。もちろんケースバイケースですが、まったく更新をしない運用は、あまり好ましいものではありません。

わかりやすい理由として、更新をしない予定のプログラムは、あとで更新をすることが少なからずあり得る、というのが現実だからです。

個人的な最小要件のバージョン管理方法

バージョン管理の手間は、なるべく小さいものにしてやるならどうするのか?

個人的には .csproj に直接バージョンを書き込んでしまう、というのが答えです。加えて、リビジョンとビルドのバージョンの部分は、CI/CD などのツールを使って自動的に数字を設定することが多いと思います。

そこで、ビルドをした年月日を設定してしまいます。メジャーとマイナーのバージョンだけは、マニュアル(手動)で管理します。

これを実現するコードが以下のとおり。.csproj に追記します。以下の文字列として表示されるはず(2024年06月12日の場合):

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net8.0-windows</TargetFramework>
    <RootNamespace>sample</RootNamespace>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <UseWPF>true</UseWPF>

    <!-- バージョンを設定 -->
    <VersionPrefix>1.0</VersionPrefix>
    <BuildNumber>$([System.DateTime]::UtcNow.ToString('yy'))</BuildNumber>
    <RevisionNumber>$([System.DateTime]::UtcNow.ToString('MMdd'))</RevisionNumber>

    <Version>$(VersionPrefix).0</Version>
    <AssemblyVersion>$(VersionPrefix).0</AssemblyVersion>
    <FileVersion>$(VersionPrefix).$(BuildNumber).$(RevisionNumber)</FileVersion>
    <!-- バージョンを設定 -->
  </PropertyGroup>

  <ItemGroup>
    ..
  </ItemGroup>

  <ItemGroup>
    ..
  </ItemGroup>

</Project>

補足として、バージョンのどこかの数字を "yyMMdd" (例えば:240612)にすればいいのではないか、と思うかもしれませんが、それは非推奨です。

各バージョンの数値は、16ビット整数(0 - 65535)の範囲が推奨されます。なので "yy" と "MMdd" に分けたりする必要があります。

プログラムからのバージョン参照

アプリケーションからは、基本的に「ファイルバージョン」を参照して表示するとよいと思います。

var version = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion ?? "(unk)";

このようにしておけば、ビルドをした年月日でプログラムを管理できる+大きな変更をしたときは、マニュアル(手動)で、メジャーバージョンかマイナーバージョンを更新する。

もしも、NuGet に公開する場合はこれに加えて一番下のバージョンは、(パッケージバージョンとアセンブリバージョンにおいて)フリーな記述ができる仕様になっています。

これはどういうことかというと、Microsoft のバージョンが下図のようになっているためです。

基本的には、大きなプロジェクトであれば、管理意識が高いためバージョンは運用されるものだと思います。しかし、社内用 or 個人用といった小さなプログラムが地味に小タスクの処理に根付いてしまい、結果的に長期運用されているケースは珍しくもないので、「ちょっとしたプログラムだから」のケースでも油断せずにバージョンをつけて表示しておこう、という話。

バージョン設定のやり方をメモしておけば、ものの数分で設定できる。

参考