web-dev-qa-db-ja.com

MSIセットアップバージョンでAssemblyInfoバージョン番号を設定する

セットアッププロジェクトを使用してプロジェクトを公開しています。各プロジェクトのバージョンをセットアップバージョンと同じにしたい。

Visual Studioでセットアップバージョンプロパティを変更したいのですが、ビルド後に、このプロパティからすべてのプロジェクトバージョンを更新することは可能ですか?

15
santBart

プロジェクトにはアセンブリとファイルのバージョン番号があります:(セットアップバージョンではなく、それに応じて質問を編集しました) enter image description here

回答1:

セットアッププロジェクトのバージョン番号を設定する場合は、アセンブリとファイルのバージョン番号を設定する必要があります。ビルドによってトリガーされるスクリプト/ exeを使用する必要があります。

enter image description here

この記事の アセンブリバージョン番号を自動的に更新する方法 は、ソリューションの半分を示しています...

私が行った調査から、PreBuildEventでSetupVersionを使用することはできません。そのための$ SetupVersionコマンドはありません: http://msdn.Microsoft.com/en-us/library/42x5kfw4(v = vs.80).aspx

-set:コマンドを使用して、コードプロジェクトの記事の このコメント に示すように、各ビルドでPreBuildEventを変更することは理想的ではありません。

必要なソリューションは、AssemblyInfoUtil.exeを呼び出し、vdprojプロジェクトファイルから「ProductVersion」を読み取るPreBuildEventです。次に、アセンブリのバージョン番号を更新します。

記事のコードを変更して、Setup.vdprojから製品バージョンを読み取る方法を示しました。これは、PreBuildEventから呼び出す方法です。

AssemblyInfoUtil.exe -setup:"C:\Program Files\MyProject1\Setup1\Setup1.vdproj" -ass:"C:\Program Files\MyProject1\AssemblyInfo.cs"

これは変更されたコードです:

using System;
using System.IO;
using System.Text;

namespace AssemblyInfoUtil
{
    class AssemblyInfoUtil
    {
    private static int incParamNum = 0;    
    private static string fileName = "";  
    private static string setupfileName = "";       
    private static string versionStr = null;    
    private static bool isVB = false;
    [STAThread]
    static void Main(string[] args)
    {
        for (int i = 0; i < args.Length; i++) {
            if (args[i].StartsWith("-setup:")) {
           string s = args[i].Substring("-setup:".Length);
           setupfileName = int.Parse(s);
            }
            else if (args[i].StartsWith("-ass:")) {
           fileName = args[i].Substring("-ass:".Length);
            }
        }

        //Jeremy Thompson showing how to detect "ProductVersion" = "8:1.0.0" in vdproj
        string setupproj = System.IO.File.ReadAllText(setupfileName);
        int startPosOfProductVersion = setupproj.IndexOf("\"ProductVersion\" = \"") +20;
        int endPosOfProductVersion = setupproj.IndexOf(Environment.NewLine, startPosOfProductVersion) - startPosOfProductVersion;
        string versionStr = setupproj.Substring(startPosOfProductVersion, endPosOfProductVersion);
        versionStr = versionStr.Replace("\"", string.Empty).Replace("8:",string.Empty);

        if (Path.GetExtension(fileName).ToLower() == ".vb")
        isVB = true;

        if (fileName == "") {
        System.Console.WriteLine("Usage: AssemblyInfoUtil 
           <path to :Setup.vdproj file> and  <path to AssemblyInfo.cs or AssemblyInfo.vb file> [options]");
        System.Console.WriteLine("Options: ");
        System.Console.WriteLine("  -setup:Setup.vdproj file path");
        System.Console.WriteLine("  -ass:Assembly file path");
        return;
        }

        if (!File.Exists(fileName)) {
        System.Console.WriteLine
            ("Error: Can not find file \"" + fileName + "\"");
        return;
        }

        System.Console.Write("Processing \"" + fileName + "\"...");
        StreamReader reader = new StreamReader(fileName);
             StreamWriter writer = new StreamWriter(fileName + ".out");
        String line;

        while ((line = reader.ReadLine()) != null) {
        line = ProcessLine(line);
        writer.WriteLine(line);
        }
        reader.Close();
        writer.Close();

        File.Delete(fileName);
        File.Move(fileName + ".out", fileName);
        System.Console.WriteLine("Done!");
    }

    private static string ProcessLine(string line) {
        if (isVB) {
        line = ProcessLinePart(line, "<Assembly: AssemblyVersion(\"");
        line = ProcessLinePart(line, "<Assembly: AssemblyFileVersion(\"");
        } 
        else {
        line = ProcessLinePart(line, "[Assembly: AssemblyVersion(\"");
        line = ProcessLinePart(line, "[Assembly: AssemblyFileVersion(\"");
        }
        return line;
    }

    private static string ProcessLinePart(string line, string part) {
        int spos = line.IndexOf(part);
        if (spos >= 0) {
        spos += part.Length;
        int epos = line.IndexOf('"', spos);
        string oldVersion = line.Substring(spos, epos - spos);
        string newVersion = "";
        bool performChange = false;

        if (incParamNum > 0) {
            string[] nums = oldVersion.Split('.');
            if (nums.Length >= incParamNum && nums[incParamNum - 1] != "*") {
            Int64 val = Int64.Parse(nums[incParamNum - 1]);
            val++;
            nums[incParamNum - 1] = val.ToString();
            newVersion = nums[0]; 
            for (int i = 1; i < nums.Length; i++) {
                newVersion += "." + nums[i];
            }
            performChange = true;
            }
        }

        else if (versionStr != null) {
            newVersion = versionStr;
            performChange = true;
        }

        if (performChange) {
            StringBuilder str = new StringBuilder(line);
            str.Remove(spos, epos - spos);
            str.Insert(spos, newVersion);
            line = str.ToString();
        }
        } 
        return line;
    }
     }
}

回答2:

私のより良い方法は、個々のAssemblyInfoクラスファイルではなく 共有アセンブリ情報 クラスを使用することです。

これを実装するには、SharedAssemblyInfo.csという名前のソリューションフォルダーにファイルを作成し、各プロジェクトでSharedAssemblyInfo.csへのリンクを追加します。以下に示すように、リンクされたSharedAssemblyInfo.csをPropertiesフォルダーに移動して、ソリューション内の各プロジェクトに固有のAssemblyInfo.csと並べて配置することもできます。

enter image description here

SharedAssemblyInfo.csファイルのサンプルを次に示します。

using System;
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: AssemblyCompany("Saint Bart Technologies")]
[Assembly: AssemblyProduct("Demo")]
[Assembly: AssemblyCopyright("Copyright ? Saint Bart 2013")]
[Assembly: AssemblyTrademark("")]

// Make it easy to distinguish Debug and Release (i.e. Retail) builds;
// for example, through the file properties window.
#if DEBUG
[Assembly: AssemblyConfiguration("Debug")]
[Assembly: AssemblyDescription("Flavor=Debug")] // a.k.a. "Comments"
#else
[Assembly: AssemblyConfiguration("Retail")]
[Assembly: AssemblyDescription("Flavor=Retail")] // a.k.a. "Comments"
#endif

[Assembly: CLSCompliant(true)]

// 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.
[Assembly: ComVisible(false)]

// Note that the Assembly version does not get incremented for every build
// to avoid problems with Assembly binding (or requiring a policy or
// <bindingRedirect> in the config file).
//
// The AssemblyFileVersionAttribute is incremented with every build in order
// to distinguish one build from another. AssemblyFileVersion is specified
// in AssemblyVersionInfo.cs so that it can be easily incremented by the
// automated build process.
[Assembly: AssemblyVersion("1.0.0.0")]

// By default, the "Product version" shown in the file properties window is
// the same as the value specified for AssemblyFileVersionAttribute.
// Set AssemblyInformationalVersionAttribute to be the same as
// AssemblyVersionAttribute so that the "Product version" in the file
// properties window matches the version displayed in the GAC Shell extension.
[Assembly: AssemblyInformationalVersion("1.0.0.0")] // a.k.a. "Product version"

次に、AssemblyInfo.csファイルのサンプルを示します。

// Note: Shared Assembly information is specified in SharedAssemblyInfo.cs
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("WindowsFormsApplication2")]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[Assembly: Guid("ffded14d-6c95-440b-a45d-e1f502476539")]

したがって、すべてのプロジェクトのアセンブリ情報を変更するたびに、1か所で変更できます。 MSIセットアップバージョンをアセンブリのバージョン番号と同じように手動で設定するとします。


回答3:

MSBuild を使用するように切り替えることを検討してください。これには、これらすべての種類の利点がありますが、今すぐ入手できるかどうかはわかりません。


回答4:

アセンブリは、AssemblyInfo.cs内の次のアスタリスク構文を使用して、ビルド番号を自動インクリメントできます。

[Assembly: AssemblyVersion("1.0.0.*")]

ビルド番号を追跡するポイントは、異なるビルドを認識できるようにすることなので、これは良い方法です。ビルドがまだ行われていないため、ビルド前にビルド番号を変更すると、この目的は無効になります。


回答5:

他の CodeProject ここでの回答は、セットアップMSIプロジェクトファイルのProductVersion, ProductCode, PackageCodeを更新することを前提としています。私はあなたの質問をそのように解釈しませんでした、そしてこのスレッドによれば問題があります: セットアッププロジェクトのProductVersionを変更するための事前ビルドイベントはビルド後まで有効になりません

Answer 6(new):

「アセンブリ情報」を設定するためのTFSビルドプラグインがいくつかあります: https://marketplace.visualstudio.com/items?itemName=bleddynrichards.Assembly-Info-Taskhttps:// marketplace.visualstudio.com/items?itemName=bool.update-Assembly-infohttps://marketplace.visualstudio.com/items?itemName=ggarbuglia.setassemblyversion-task

36
Jeremy Thompson

これで問題が完全に解決されるかどうかはわかりませんが、次のようなすべての構成管理情報を含む共通クラスを実装できます。

public class VersionInfo{
    public const string cProductVersion = "1.0.0"
    //other version info
}

すべてのAssemblyInfo.csを新しいクラスで更新できるようになった後:

[Assembly: AssemblyVersion(VersionInfo.cProductVersion)]

これがお役に立てば幸いです。

2
yaens