Help us understand the problem. What is going on with this article?

VisualStudio の T4 で AssemblyInfo.cs を一括置換する

More than 5 years have passed since last update.

はじめに

ソリューションの中にたくさんのプロジェクトがあって、それを全部AssemblyVersion.csでバージョン指定してあると、バージョン番号の変更が大変ですよね。

ちょっと別ツールでそういう変更をやってくれるツールを作ったりもしていたのですが、Visual Studioの標準機能でもできるらしい。ということでメモを兼ねて投稿。

T4 テンプレート

T4 というテンプレートが Visual Studio には組み込まれているので、それを使うとビルド前に自動的にファイルのテンプレート展開をやってくれる。

T4 テンプレートの適用は簡単で、プロジェクトに新しい項目の追加で「テキストテンプレート」を選べば良い。

デフォルトではこんなファイルが出来上がる。名前は AssemblyInfo.tt にしておく。この段階ではプロジェクトの直下に作る。

T4
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".txt" #>

まずは output extension の項目を .cs に変更して、.cs ファイルを生成するようにしよう。ついでに hostspecific を true にして Visual Studio のファイルパスにアクセスできるようにしておく。

で、この後の内容にもともとの AssemblyInfo.cs をコピーしてくる。コピーしたら元の AssemblyInfo.cs はいらなくなるので削除する(そうしないと、Properties の下に移動できない)。
削除が終わったら、プロジェクトの直下にあった AssembyInfo.tt を Properties の下に移動する。

このままではまだ AssemblyInfo.tt を手書きで書き直さないといけないので、共通のファイルを読みにいくように変更しよう。

ソリューションの直下に以下のようなVersion.t4ファイルを作る。

<#
    int majorVersion = 1;
    int minorVersion = 2;
    int buildNumber = 1;
    int revision = 1;
#>

このファイルを読み込むように AssemblyInfo.tt にコードを書こう。
include ディレクティブを書けばよい。

<#@ include file="..\..\Version.t4" #>

このバージョン番号を使ってバージョン文字列を生成しよう。

<#
    string verString = String.Format("{0}.{1}.{2}.{3}", majorVersion, minorVersion, buildNumber, revision);
#>

で、この値を使って AssemblyVerion, AssemblyFileVersion を書き換えよう。

[assembly: AssemblyVersion("<#= verString #>")]
[assembly: AssemblyFileVersion("<#= verString #>")]

バージョンを変えたときに自動的にT4変換を実行させる

このままだと、.ttファイルを編集しないと Visual Studio は「変えなくて良いんだな~」と判断して、AssemblyInfo.cs を変更してくれない。そこで、拡張機能の「AutoT4」をインストールする。インストールすると設定不要で、いつでも.tt を変換してくれるようになる。

Jenkins との連携

Jenkins (というか MSBuild)で自動的にテンプレート変換を実行するには骨が折れる様子。
http://mediaingenuity.github.io/2013/12/18/text-template-transformation-t4-integration-msbuild.html このページを参考にすればいけそうだが・・・?

以下を入れた上でちょっと色々いじるらしい。
Visual Studio 2013 SDK
https://www.microsoft.com/en-us/download/details.aspx?id=40758

Modeling SDK for Microsoft Visual Studio 2013
https://www.microsoft.com/en-us/download/details.aspx?id=40754

2010はこれ
Visual Studio 2010 SDK
https://www.microsoft.com/en-us/download/details.aspx?id=2680

2010SP1だとこれ。SP1当ててると上のは動かない。
http://www.microsoft.com/en-us/download/details.aspx?id=21835

Microsoft Visual Studio 2010 Visualization & Modeling SDK
https://www.microsoft.com/en-us/download/details.aspx?id=23025

2012も似たような名前なので適当に探して欲しい

.csprojに以下の変更を加える。Projectタグの直下でOKらしい。

<PropertyGroup>
  <TransformOnBuild>True</TransformOnBuild>
  <TransformOutOfDateOnly>false</TransformOutOfDateOnly>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TextTemplating\Microsoft.TextTemplating.targets" />

・・・Visual Studio2013で作ってるんだけど、.Net Framework の4.5にしているせいか、$(VisualStudioVersion)がv11.0になるせいでビルドできない・・・

手順@VS2010

まずは適当なプロジェクトを作る。

20150628-175411.png

新しい項目でAssemblyInfo.ttを作る。

20150628-175725.png

できたらProperties以下に移動する。

ソリューション直下に各プロジェクトで共通で使うバージョン番号のテンプレートファイルを作る。
20150628-180448.png

AssemblyInfo.ttを変更する。
20150628-181016.png

・・・と、ここまで書いておいて、Version.t4の変更を検知して.ttの再変換を行ってくれる方法が必要なことに気づいた。

http://www.matthiaseinig.de/2013/05/20/auto-generate-fileversion-for-all-projects-in-a-solution-with-t4/ では、AssemblyInfoを共通のファイルを使うやり方を紹介している。

MSBuildでT4変換できるようにすれば、ビルド前イベントでこうすれば良いようだ。

%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "$(ProjectPath)" /t:TransformAll

残る問題はチーム開発でこれ全部インストールする必要があることかな・・・
試してないけど、Importをこうやれば、VS SDK/Modeling SDKをインストールしていなくてもビルドエラーが出ないようになる・・・かも?

<Import Condition="Exists('$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TextTemplating\v$(VisualStudioVersion)\Microsoft.TextTemplating.targets')" Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TextTemplating\v$(VisualStudioVersion)\Microsoft.TextTemplating.targets" />

追記

こんな感じの定義を.csprojの最後に入れればビルド前イベントでMSBuildを使わなくてもOKのようだ。一応、ファイルの有無チェックをしているので、VS SDK、VS Modeling SDKを入れてなくてもエラーは出ないはず・・・多分。

.csproj
  <PropertyGroup>
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
    <T4Path>$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TextTemplating\Microsoft.TextTemplating.targets</T4Path>
    <T4Path Condition="'$(VisualStudioVersion)' == '10.0'">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TextTemplating\v$(VisualStudioVersion)\Microsoft.TextTemplating.targets</T4Path>
  </PropertyGroup>
  <Import Condition="Exists('$(T4Path)')" Project="$(T4Path)" />
  <PropertyGroup Condition="Exists('$(T4Path)')">
    <TranformOnBuild>true</TranformOnBuild>
    <TransformOutOfDateOnly>false</TransformOutOfDateOnly>
    <BuildDependsOn>
      TransformAll;
      BeforeBuild;
      CoreBuild;
      AfterBuild;
    </BuildDependsOn>
  </PropertyGroup>
kounoike
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした