5
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

C#でビルド時にバージョン番号とか埋め込みたい時はAssemblyInfoに埋め込む

Last updated at Posted at 2021-04-09

要約

以下が非常に詳しいです。

2022/07/21 追記: 日付を埋め込む場合は、次のmsbuildのProperty functionsを使ったやり方がよいでしょう。次のStackoverflowの回答もご覧ください。

メモ

例えばWebAPIやアプリケーションのメタ情報として今のバージョンやビルドした日時やGitのハッシュ値が欲しくなる時があります。

アップデート前後でアクセス数の変化を見たり、問題が入り始めた時にモジュールのバージョンやビルドの日時やコミットIDがわかると原因の特定がしやすくなります。

C#(.Net)ではAssemblyInfoを利用すると色々埋め込んだり取得できるらしいですが、色々ある上に色々注意が必要でした。

Version

プロジェクトファイルを以下のようにします

MyProjectNameSpace.csproj
  <PropertyGroup>
    <Version>1.2.3.4</Version> <!-- これを追加 -->
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

コードから読むときはこんな感じにします。クラス名はビルドで生成される成果物(dll等)に埋め込まれるクラス名にします。

MyProjectNameSpace/Application.cs
// これはダメらしくnullになる
// string Version = typeof(Application).Assembly.GetCustomAttribute<AssemblyVersionAttribute>()?.Version;
// こうする
string Version = typeof(Application).Assembly.GetName().Version.ToString();

AssemblyVersionAttribute で得られそうですが、nullになります。調べたところ、Assembly.GetName()を使えとのことでした。

ToStringしていますが、Versionからはメジャーバージョン、マイナーバージョン等、細かく取ることもできます。

InformationVersion

MyProjectNameSpace/Application.cs
string InformationVersion = typeof(Application).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;

Version1.2.3.4 のとき、特に何もしていない場合はInformationVersion1.2.3.4になります。
しかしdotnet build /p:SourceRevisionId=asdf とすると、InformationVersion1.2.3.4+asdfが得られるという感じです。

CIのビルド時にチェックアウトしてきたGitのCommitIdを入れたりするとよさそうです。最近のCIサービスはGitのCommitIDぐらいは環境変数に入ってきます。

ビルド日時とかは?

Assemblyにはないようです。以下の記事で見た感じ、いくつか方法がありそうです。

いくつかやり方はあるみたいですが、以下の2つを試しました。

  • Assemblyのメタデータに埋め込んで取り出す
  • リソースファイルとして埋め込む

Assemblyのメタデータに埋め込んで取り出す

多分これが一番楽だと思います。StackOverflowの記事でも回答についています

msbuildのProperty functionsなる機能のおかげで簡単な式を書けるので、これでビルド時に評価させて埋め込むことができます。

Sample.csproj
  <ItemGroup>

    <!-- 追加 -->
    <AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
      <_Parameter1>BuildDateTime</_Parameter1>
      <_Parameter2>$([System.DateTime]::UtcNow.ToString("o"))</_Parameter2> <!-- 2021-07-21T00:00:00.000000Z -->
    </AssemblyAttribute>
  </ItemGroup>

とやってビルドし、そのAssemblyに対して以下のようなコードを書けば読みだせます。


// AssemblyはAssemblyにあるクラスのTypeからリフレクションで取り出せます
// 例: var assembly = typeof(MyClass).Assembly;

public static string LoadBuildDateTime(Assembly assembly){
    var metadata = assembly
        .GetCustomAttributes<AssemblyMetadataAttribute>()
        ?.Where(a => a.Key == "BuildDateTime") // Key は _Parameter1 の値と合わせる
        ?.FirstOrDefault();
    if (metadata != null)
    {
        return metadata.Value;
        // ParseしてDateTimeで返す場合は以下
        // return DateTime.ParseExact(metadata.Value, "o", CultureInfo.InvariantCulture);
    }
    return null;
}

リソースファイルを使うやり方

リソースファイルの埋め込み方は以下です。(厳密にバイナリが作られた日時ではないけど。)

  • プロジェクトファイルにリソースファイルの場所を書く
  • リソースファイルを用意する
  • Assembly.GetManifestResourceStreamを使って読み込む

プロジェクトファイルにリソースファイルの場所を書く

MyProjectNameSpace/MyProjectNameSpace.csproj
<Project Sdk="Microsoft.NET.Sdk.Web">
  <!-- 中略 -->
  <ItemGroup>
    <EmbeddedResource Include="Properties/BuildDate.txt" /><!-- ここ追加 -->
  </ItemGroup>
</Project>

リソースファイルを用意する。開発時はダミーでもいいのでこんな風に用意しておきます

MyProjectNameSpace/Properties/BuildDate.txt
1970-01-01T00:00:00,0000000000+09:00

Assembly.GetManifestResourceStreamを使って読み込む(実際は初回1回だけ読むとかしたほうが良いかもしれない)

MyProjectNameSpace/Application.cs
        private readonly string BuildDate = ReadStringFromResource("MyProjectNameSpace.Properties.BuildDate.txt");

        private static string ReadStringFromResource(string resourceName)
        {
            using (var stream = new StreamReader(GetAssembly().GetManifestResourceStream(resourceName)))
            {
                return stream.ReadToEnd();
            }
        }

あとはProperties/BuildDate.txt をCI時に作ってやればよいという感じです。

5
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?