ビルド時に自動インクリメントされる整数のセットを保存したいです。
int MajorVersion = 0;
int MinorVersion = 1;
int Revision = 92;
コンパイルすると、Revision
が自動的にインクリメントされます。私がセットアッププロジェクトをビルドするとき、それはMinorVersion
をインクリメントするでしょう(私はこれを手動でやっても大丈夫です)。 MajorVersion
は手動でのみインクリメントされます。
それから私はメニューHelp/Aboutでバージョン番号をユーザーに表示することができます。
バージョン:0.1.92
どうすればこれを達成できますか?
この質問では、自動インクリメントするバージョン番号の付け方だけでなく、他のものよりも完全な答えであるコード内でのそれの使い方も尋ねています。
プロジェクトに AssemblyInfo クラスを追加し、アスタリスクで終わるようにAssemblyVersion属性を修正したとします。次に例を示します。
[Assembly: AssemblyVersion("2.10.*")]
Visual Studioは これらの規則 に従ってあなたのためにあなたのための最終的な数を増加させるでしょう。
このバージョンをコードで参照してユーザーに表示できるようにするには、リフレクションを使用します。例えば、
Version version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
DateTime buildDate = new DateTime(2000, 1, 1)
.AddDays(version.Build).AddSeconds(version.Revision * 2);
string displayableVersion = $"{version} ({buildDate})";
AssemblyVersion
とAssemblyFileVersion
の両方が指定されていると、.exeには表示されません。
4番目の数字だけを*
に設定することは、バージョンが常に増加するわけではないので、悪い結果になる可能性があります。 3番目の数字は2000年以降の日数で、4番目の数字は午前0時からの秒数(2で除算)です[IT IS NOT RANDOM]。そのため、1日のうちに遅く、翌日の1日のうちに早くソリューションをビルドした場合、後のビルドの方が古いバージョン番号になります。あなたのバージョン番号は常にこのように増加するので、私は常にX.Y.*
の代わりにX.Y.Z.*
を使うことを勧めます。
単純なテキストファイルから必要なソースコードを生成するためにVisual Studioで T4テンプレートメカニズムを使用することができます 。
私はいくつかの.NETプロジェクトのバージョン情報生成を設定したいと思いました。利用可能なオプションを調査してから長い時間が経ったので、これを行う簡単な方法を見つけることを望んで周りを検索しました。人々が1つの整数を取得するためにVisual StudioアドインとカスタムMsBuildタスクを書くのは、非常に心強いとは思われませんでした。これは小さな個人的なプロジェクトにはやり過ぎだと感じました。
T4テンプレートがその仕事をすることができると誰かが提案したStackOverflowの議論の1つからインスピレーションを得ました。そしてもちろん可能です。このソリューションは最小限の労力でVisual Studioやビルドプロセスのカスタマイズを必要としません。ここですべきことは次のとおりです。
- 拡張子が「.tt」のファイルを作成し、AssemblyVersion属性とAssemblyFileVersion属性を生成するT4テンプレートをそこに配置します。
<#@ template language="C#" #>
//
// This code was generated by a tool. Any changes made manually will be lost
// the next time this code is regenerated.
//
using System.Reflection;
[Assembly: AssemblyVersion("1.0.1.<#= this.RevisionNumber #>")]
[Assembly: AssemblyFileVersion("1.0.1.<#= this.RevisionNumber #>")]
<#+
int RevisionNumber = (int)(DateTime.UtcNow - new DateTime(2010,1,1)).TotalDays;
#>
あなたはバージョン番号生成アルゴリズムについて決める必要があるでしょう。私には、2010年1月1日からの日数に設定されたリビジョン番号を自動生成するだけで十分でした。ご覧のとおり、バージョン生成規則はプレーンC#で書かれているので、必要に応じて簡単に調整できます。
- 上記のファイルはいずれかのプロジェクトに配置する必要があります。私はバージョン管理手法を明確にするために、この単一のファイルだけで新しいプロジェクトを作成しました。このプロジェクトをビルドすると(実際にはビルドする必要さえありません。ファイルを保存するだけでVisual Studioのアクションが起動されます)、次のC#が生成されます。
//
// This code was generated by a tool. Any changes made manually will be lost
// the next time this code is regenerated.
//
using System.Reflection;
[Assembly: AssemblyVersion("1.0.1.113")]
[Assembly: AssemblyFileVersion("1.0.1.113")]
はい、今日は2010年1月1日から113日です。明日の改訂番号は変わります。
- 次のステップは、同じ自動生成されたバージョン情報を共有する必要があるすべてのプロジェクトのAssemblyInfo.csファイルからAssemblyVersion属性とAssemblyFileVersion属性を削除することです。代わりに、プロジェクトごとに「既存の項目を追加」を選択し、T4テンプレートファイルのあるフォルダに移動し、対応する「.cs」ファイルを選択してリンクとして追加します。それはします!
このアプローチについて私が気に入っているのは、それが軽量で(カスタムMsBuildタスクがない)、そして自動生成されたバージョン情報がソース管理に追加されていないことです。そしてもちろん、バージョン生成アルゴリズムにC#を使用することは、どんな複雑さのアルゴリズムに対しても可能です。
これはT4提案の私の実装です...これは選択された設定(すなわちDebug | Release)に関係なくプロジェクトをビルドするたびにビルド番号をインクリメントし、Releaseビルドをするたびにリビジョン番号をインクリメントします。メジャーバージョン番号とマイナーバージョン番号の更新は、アプリケーション➤アセンブリ情報...を使って続けられます。
より詳しく説明するために、これは既存のAssemblyInfo.cs
ファイルを読み、そしてAssemblyVersion
情報を見つけるためにregexを使い、そしてTextTransform.exe
からの入力に基づいてリビジョンとビルド番号をインクリメントします。
AssemblyInfo.cs
ファイルを削除してください。代わりにAssemblyInfo.tt
ファイルを作成してください。 T4ファイルを保存した後、Visual StudioはAssemblyInfo.cs
を作成し、それをT4ファイルとグループ化する必要があります。
<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#
string output = File.ReadAllText(this.Host.ResolvePath("AssemblyInfo.cs"));
Regex pattern = new Regex("AssemblyVersion\\(\"(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<revision>\\d+)\\.(?<build>\\d+)\"\\)");
MatchCollection matches = pattern.Matches(output);
if( matches.Count == 1 )
{
major = Convert.ToInt32(matches[0].Groups["major"].Value);
minor = Convert.ToInt32(matches[0].Groups["minor"].Value);
build = Convert.ToInt32(matches[0].Groups["build"].Value) + 1;
revision = Convert.ToInt32(matches[0].Groups["revision"].Value);
if( this.Host.ResolveParameterValue("-","-","BuildConfiguration") == "Release" )
revision++;
}
#>
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Resources;
// General Information
[Assembly: AssemblyTitle("Insert title here")]
[Assembly: AssemblyDescription("Insert description here")]
[Assembly: AssemblyConfiguration("")]
[Assembly: AssemblyCompany("Insert company here")]
[Assembly: AssemblyProduct("Insert product here")]
[Assembly: AssemblyCopyright("Insert copyright here")]
[Assembly: AssemblyTrademark("Insert trademark here")]
[Assembly: AssemblyCulture("")]
// Version informationr(
[Assembly: AssemblyVersion("<#= this.major #>.<#= this.minor #>.<#= this.revision #>.<#= this.build #>")]
[Assembly: AssemblyFileVersion("<#= this.major #>.<#= this.minor #>.<#= this.revision #>.<#= this.build #>")]
[Assembly: NeutralResourcesLanguageAttribute( "en-US" )]
<#+
int major = 1;
int minor = 0;
int revision = 0;
int build = 0;
#>
これをビルド前のイベントに追加します。
"%CommonProgramFiles(x86)%\Microsoft shared\TextTemplating\$(VisualStudioVersion)\TextTransform.exe" -a !!BuildConfiguration!$(Configuration) "$(ProjectDir)Properties\AssemblyInfo.tt"
ビルドとリビジョンのためにアスタリスクを入れると、visual studioはビルド番号として2000年1月1日からの日数を使用し、真夜中からの秒数をリビジョンとして2で割った値を使用します。
はるかに優れたライフセーバーソリューションは、 http://autobuildversion.codeplex.com/ です。
それは魅力のように働きます、そしてそれは非常に柔軟です。
これがMSDNからのAssemblyInfo.csの 引用です :
すべての値を指定することも、アスタリスク()を使用してデフォルトのビルド番号、リビジョン番号、またはその両方を受け入れることもできます。たとえば、[Assembly:AssemblyVersion( "2.3.25.1")]は、メジャーバージョンとして2、マイナーバージョンとして3、ビルド番号として25、リビジョン番号として1を示します。 [Assembly:AssemblyVersion( "1.2。")]などのバージョン番号は、メジャーバージョンとして1、マイナーバージョンとして2を指定し、デフォルトのビルド番号とリビジョン番号を受け入れます。 [Assembly:AssemblyVersion( "1.2.15。*")]などのバージョン番号は、メジャーバージョンとして1、マイナーバージョンとして2、ビルド番号として15を指定し、デフォルトのリビジョン番号を受け入れます。デフォルトのビルド番号は毎日増加します。デフォルトのリビジョン番号はランダムです
これは事実上、アセンブリ情報に1.1。*を入力した場合、ビルド番号のみが自動インクリメントされ、ビルドごとにではなく毎日発生します。リビジョン番号はビルドごとに変わりますが、インクリメント方式ではなくランダムに変更されます。
ほとんどのユースケースではこれでおそらく十分です。それがあなたが探しているものでなければ、ビルド前の段階でバージョンを自動インクリメントするスクリプトを書く必要があります。
AssemblyInfo.csを使用する
App_Code:にファイルを作成し、次の情報を入力するか、他の属性/プロパティの可能性としてGoogleを使用します。
AssemblyInfo.cs
using System.Reflection;
[Assembly: AssemblyDescription("Very useful stuff here.")]
[Assembly: AssemblyCompany("companyname")]
[Assembly: AssemblyCopyright("Copyright © me 2009")]
[Assembly: AssemblyProduct("NeatProduct")]
[Assembly: AssemblyVersion("1.1.*")]
AssemblyVersionはあなたが本当に後にいる部分です。
Webサイト、任意のaspxページ、またはコントロールで作業している場合は、<Page>タグに次のコードを追加できます。
CompilerOptions="<folderpath>\App_Code\AssemblyInfo.cs"
(folderpathを適切な変数に置き換えます)。
私はあなたが他のクラスのために何らかの方法でコンパイラオプションを追加する必要があるとは思わない。 App_Code内のすべてのものは、コンパイル時にバージョン情報を受け取るはずです。
それが役立つことを願っています。
あなたはMatt Griffithによる UpdateVersion を試してみることができます。今はかなり古いですが、うまくいきます。これを使用するには、AssemblyInfo.csファイルを指すビルド前のイベントを設定するだけで、アプリケーションはコマンドライン引数に従ってバージョン番号を更新します。
アプリケーションはオープンソースなので、(メジャーバージョン)。(マイナーバージョン)。([year] [dayofyear])の形式でバージョン番号をインクリメントするバージョンも作成しました。 これについての更なる情報と改訂されたコードは私のブログエントリで利用可能です、 アセンブリバージョン番号と.NET 。
更新:私は自分の修正したバージョンのUpdateVersionアプリケーションのコードをGitHubに置いています。 https://github.com/munr/UpdateVersion
バージョンの星( "2.10.3。*"のように) - それは単純ですが、数が大きすぎます
AutoBuildVersion - 素晴らしく見えますが、私のVS2010では動作しません。
@ DrewChapinのスクリプトは機能しますが、スタジオではDebug pre-build eventとRelease pre-build eventに異なるモードを設定することはできません。
スクリプトを少し変更しました... commamd:
"%CommonProgramFiles(x86)%\Microsoft shared\TextTemplating\10.0\TextTransform.exe" -a !!$(ConfigurationName)!1 "$(ProjectDir)Properties\AssemblyInfo.tt"
とスクリプト(これは "Debug"と "Release"の設定に有効です):
<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ Assembly name="System.Windows.Forms" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#
int incRevision = 1;
int incBuild = 1;
try { incRevision = Convert.ToInt32(this.Host.ResolveParameterValue("","","Debug"));} catch( Exception ) { incBuild=0; }
try { incBuild = Convert.ToInt32(this.Host.ResolveParameterValue("","","Release")); } catch( Exception ) { incRevision=0; }
try {
string currentDirectory = Path.GetDirectoryName(Host.TemplateFile);
string assemblyInfo = File.ReadAllText(Path.Combine(currentDirectory,"AssemblyInfo.cs"));
Regex pattern = new Regex("AssemblyVersion\\(\"\\d+\\.\\d+\\.(?<revision>\\d+)\\.(?<build>\\d+)\"\\)");
MatchCollection matches = pattern.Matches(assemblyInfo);
revision = Convert.ToInt32(matches[0].Groups["revision"].Value) + incRevision;
build = Convert.ToInt32(matches[0].Groups["build"].Value) + incBuild;
}
catch( Exception ) { }
#>
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an Assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an Assembly.
[Assembly: AssemblyTitle("Game engine. Keys: F2 (Debug trace), F4 (Fullscreen), Shift+Arrows (Move view). ")]
[Assembly: AssemblyProduct("Game engine")]
[Assembly: AssemblyDescription("My engine for game")]
[Assembly: AssemblyCompany("")]
[Assembly: AssemblyCopyright("Copyright © Name 2013")]
[Assembly: AssemblyTrademark("")]
[Assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this Assembly not visible
// to COM components. If you need to access a type in this Assembly from
// COM, set the ComVisible attribute to true on that type. Only Windows
// assemblies support COM.
[Assembly: ComVisible(false)]
// On Windows, the following GUID is for the ID of the typelib if this
// project is exposed to COM. On other platforms, it unique identifies the
// title storage container when deploying this Assembly to the device.
[Assembly: Guid("00000000-0000-0000-0000-000000000000")]
// Version information for an Assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
[Assembly: AssemblyVersion("0.1.<#= this.revision #>.<#= this.build #>")]
[Assembly: AssemblyFileVersion("0.1.<#= this.revision #>.<#= this.build #>")]
<#+
int revision = 0;
int build = 0;
#>
ビルドバージョン管理 などのビルドスクリプトを使用して、より高度なバージョン管理を実行できます