.NET プログラムにおけるバージョン番号指定
.NET プログラミングの話。
自分が開発している C# プログラムや NuGet パッケージのバージョン番号の指定方法として、自分はプロジェクトファイル (.csproj) 内の "Version" MSBuild プロパティに記述するようにしている (下記例)。
<!-- 📄 ...csproj -->
<Project ...>
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Version>1.2.3.4</Version>
...
関連して、以前にこんな記事も書いた。
プレビュー版であることをバージョン番号で表現する
さてそのような .NET プログラミングにおけるバージョン番号指定だが、正式リリース前のバージョンを表現したいときに、例えば "1.2.3.4-preview.5" みたいなバージョン番号を付けたいことがある。その場合は実直にそのまま "Version" MSBuild プロパティに記述すればよい (下記例)。
<Version>1.2.3.4-preview.5</Version>
例えば Hoge.csproj ファイルに上記のように記述して "dotnet pack" を実行して NuGet パッケージを生成したら、"Hoge.1.2.3.4-preview.5.nupkg" というファイル名で NuGet パッケージファイルを生成してくれる。
自身のバージョン番号文字列を取得する方法
さてところで、こうしてプロジェクトファイル (.csproj) ファイル内で "Version" MSBuild プロパティとして設定したバージョン番号を、その .NET プログラム自身で取得したいということがままある (そのプログラムの "バージョン情報" ダイアログの実装時とか)。その場合、一般的には、以下のような C# コードで、System.Version クラスのオブジェクトでバージョン番号情報を取得可能だ。
// なんらかの手段で、その .NET プログラムの
// アセンブリの参照を取得 (下記は一例)
var assembly = this.GetType().Assembly;
// アセンブリの参照からバージョン情報 (System.Version) を取得
var version = assembly.GetName().Version;
しかしながら上記の方法だと、先に述べたような "-preview.5" みたいなバージョン番号にサフィックスを付けていた場合、そのサフィックス部分は取得できない。そもそも System.Version クラスには、そのようばバージョン番号サフィックスを格納するようなプロパティが用意されていない。
ということで、バージョン番号サフィックスも含めたバージョン番号文字列をプログラム内から取得したい場合は、次のようにする。
// なんらかの手段で、その .NET プログラムの
// アセンブリの参照を取得 (これは前記の方式と変わらず)
var assembly = this.GetType().Assembly;
// アセンブリに付与されている AssemblyInformationalVersion 属性を取得
var verInfo = assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>();
// するとその AssemblyInformationalVersion 属性の
// InformationalVersion プロパティ (string 型) に、
// "1.2.3.4-preview.5" のようなバージョン番号文字列が入っている
verInfo.InformationalVersion;
バージョン番号サフィックスに何かハッシュ値!?
さて、上記の仕組みで自身のバージョン番号を表示するとある .NET プログラムを保守運用しており、まだ正式リリース前の .NET 8 SDK プレビュー版も先行評価のために使用してビルドしていた。
そんなあくる日、.NET 8 SDK の Preview 4 がリリースされたので、Preview 3 から Preview 4 への移行を行なって動作確認を実施。すると、その .NET プログラムのバージョン番号表示が、"1.2.3.4-preview.5+e9bd4d4...." というように、何やら末尾に何かのハッシュ値が付与されるようになってしまっていた。
どうやら .NET 8 SDK Preview 4 から、何かしらソースコードのハッシュに関する値が設定されるようになったらしい。それなりに意味のある仕様変更なのだとは思うが、取り急ぎは従来どおりの動作にしたかったため、このハッシュ値がビルド処理のどこで設定されているのかを調べてみた。
調べてみた
具体的には、"dotnet build /bl:{ファイル名}" を実行し、MSBuild のバイナリ実行ログをファイルに出力して、それを MSBuild Structured Log Viewer ( https://msbuildlog.com/ ) で開いて調べてみた。
すると幸い、.NET SDK に収録されている MSBuild スクリプトファイル
C:\Program Files\dotnet\sdk\8.0.100-preview.4.23260.5\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.GenerateAssemblyInfo.targets
の 61 行目にある、"AddSourceRevisionToInformationalVersion" Target で、このハッシュ値の付加が行なわれていることを特定できた。かつ、この "AddSourceRevisionToInformationalVersion" Target には Condition 属性も設定されていて、そこには
'$(IncludeSourceRevisionInInformationalVersion)' == 'true'
の条件が書かれているのを見つけた。すなわち、この MSBuild プロパティ "IncludeSourceRevisionInInformationalVersion" を false に設定しておけばこの Condition が満たされず、結果、ハッシュ値の付加処理がスキップされるはずだ。
ということで、プロジェクトファイル (.csproj) 内に以下のように MSBuild プロパティを書き足して再度ビルドしたところ、
<!-- 📄 ...csproj -->
<Project ...>
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Version>1.2.3.4-preview.5</Version>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
...
当該プログラムのバージョン番号表示を "1.2.3.4-preview.5" に戻すことができた。
回避方法がわかったので、改めて MSBuild プロパティ名 "IncludeSourceRevisionInInformationalVersion" をキーワードにネットで検索してみると、このハッシュ値付加の仕組みはずいぶん昔からある模様。2018 年時点のブログ記事に言及があるのを見つけた (下記リンク先)。
https://andrewlock.net/version-vs-versionsuffix-vs-packageversion-what-do-they-all-mean/
まとめ
現時点では、どうして .NET 8 SDK Preview 4 からこの仕様になったのか、その背景事情を理解していないのだが、とりあえずは従来と同じ動作に戻すことができることがわかって一安心。引き続きはこの仕様変更の理由を確認して、理想の対応方法・この仕組みの利用方法は何なのか、理解を深めておきたいところである。
.NET プログラミングの話。
自分が開発している C# プログラムや NuGet パッケージのバージョン番号の指定方法として、自分はプロジェクトファイル (.csproj) 内の "Version" MSBuild プロパティに記述するようにしている (下記例)。
<!-- 📄 ...csproj -->
<Project ...>
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Version>1.2.3.4</Version>
...
関連して、以前にこんな記事も書いた。
プレビュー版であることをバージョン番号で表現する
さてそのような .NET プログラミングにおけるバージョン番号指定だが、正式リリース前のバージョンを表現したいときに、例えば "1.2.3.4-preview.5" みたいなバージョン番号を付けたいことがある。その場合は実直にそのまま "Version" MSBuild プロパティに記述すればよい (下記例)。
<Version>1.2.3.4-preview.5</Version>
例えば Hoge.csproj ファイルに上記のように記述して "dotnet pack" を実行して NuGet パッケージを生成したら、"Hoge.1.2.3.4-preview.5.nupkg" というファイル名で NuGet パッケージファイルを生成してくれる。
自身のバージョン番号文字列を取得する方法
さてところで、こうしてプロジェクトファイル (.csproj) ファイル内で "Version" MSBuild プロパティとして設定したバージョン番号を、その .NET プログラム自身で取得したいということがままある (そのプログラムの "バージョン情報" ダイアログの実装時とか)。その場合、一般的には、以下のような C# コードで、System.Version クラスのオブジェクトでバージョン番号情報を取得可能だ。
// なんらかの手段で、その .NET プログラムの
// アセンブリの参照を取得 (下記は一例)
var assembly = this.GetType().Assembly;
// アセンブリの参照からバージョン情報 (System.Version) を取得
var version = assembly.GetName().Version;
しかしながら上記の方法だと、先に述べたような "-preview.5" みたいなバージョン番号にサフィックスを付けていた場合、そのサフィックス部分は取得できない。そもそも System.Version クラスには、そのようばバージョン番号サフィックスを格納するようなプロパティが用意されていない。
ということで、バージョン番号サフィックスも含めたバージョン番号文字列をプログラム内から取得したい場合は、次のようにする。
// なんらかの手段で、その .NET プログラムの
// アセンブリの参照を取得 (これは前記の方式と変わらず)
var assembly = this.GetType().Assembly;
// アセンブリに付与されている AssemblyInformationalVersion 属性を取得
var verInfo = assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>();
// するとその AssemblyInformationalVersion 属性の
// InformationalVersion プロパティ (string 型) に、
// "1.2.3.4-preview.5" のようなバージョン番号文字列が入っている
verInfo.InformationalVersion;
バージョン番号サフィックスに何かハッシュ値!?
さて、上記の仕組みで自身のバージョン番号を表示するとある .NET プログラムを保守運用しており、まだ正式リリース前の .NET 8 SDK プレビュー版も先行評価のために使用してビルドしていた。
そんなあくる日、.NET 8 SDK の Preview 4 がリリースされたので、Preview 3 から Preview 4 への移行を行なって動作確認を実施。すると、その .NET プログラムのバージョン番号表示が、"1.2.3.4-preview.5+e9bd4d4...." というように、何やら末尾に何かのハッシュ値が付与されるようになってしまっていた。
どうやら .NET 8 SDK Preview 4 から、何かしらソースコードのハッシュに関する値が設定されるようになったらしい。それなりに意味のある仕様変更なのだとは思うが、取り急ぎは従来どおりの動作にしたかったため、このハッシュ値がビルド処理のどこで設定されているのかを調べてみた。
調べてみた
具体的には、"dotnet build /bl:{ファイル名}" を実行し、MSBuild のバイナリ実行ログをファイルに出力して、それを MSBuild Structured Log Viewer ( https://msbuildlog.com/ ) で開いて調べてみた。
すると幸い、.NET SDK に収録されている MSBuild スクリプトファイル
C:\Program Files\dotnet\sdk\8.0.100-preview.4.23260.5\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.GenerateAssemblyInfo.targets
の 61 行目にある、"AddSourceRevisionToInformationalVersion" Target で、このハッシュ値の付加が行なわれていることを特定できた。かつ、この "AddSourceRevisionToInformationalVersion" Target には Condition 属性も設定されていて、そこには
'$(IncludeSourceRevisionInInformationalVersion)' == 'true'
の条件が書かれているのを見つけた。すなわち、この MSBuild プロパティ "IncludeSourceRevisionInInformationalVersion" を false に設定しておけばこの Condition が満たされず、結果、ハッシュ値の付加処理がスキップされるはずだ。
ということで、プロジェクトファイル (.csproj) 内に以下のように MSBuild プロパティを書き足して再度ビルドしたところ、
<!-- 📄 ...csproj -->
<Project ...>
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Version>1.2.3.4-preview.5</Version>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
...
当該プログラムのバージョン番号表示を "1.2.3.4-preview.5" に戻すことができた。
回避方法がわかったので、改めて MSBuild プロパティ名 "IncludeSourceRevisionInInformationalVersion" をキーワードにネットで検索してみると、このハッシュ値付加の仕組みはずいぶん昔からある模様。2018 年時点のブログ記事に言及があるのを見つけた (下記リンク先)。
https://andrewlock.net/version-vs-versionsuffix-vs-packageversion-what-do-they-all-mean/
まとめ
現時点では、どうして .NET 8 SDK Preview 4 からこの仕様になったのか、その背景事情を理解していないのだが、とりあえずは従来と同じ動作に戻すことができることがわかって一安心。引き続きはこの仕様変更の理由を確認して、理想の対応方法・この仕組みの利用方法は何なのか、理解を深めておきたいところである。