【问题标题】:How to programmatically change a project's product version?如何以编程方式更改项目的产品版本?
【发布时间】:2010-09-23 07:16:36
【问题描述】:

我有几个部署项目。为了部署一个应用程序,我需要做几项任务,其中之一是更改每个部署项目的产品版本和产品代码。

我找不到以编程方式更改它们的方法。

由于它是一个部署项目(最终生成一个可执行安装程序),我无法使用 MSBuild,而是在命令提示符下使用 Devenv。

【问题讨论】:

  • 这是什么类型的项目? c++ 还是 c#/vb?
  • 该项目是一个C#部署项目,我使用的是.Net 2.0。
  • 有完整源代码的最终解决方案吗?是 vdproj 项目吗?
  • 这是一个 csproj。没有最终的工作解决方案。

标签: visual-studio-2005 automated-deploy


【解决方案1】:

我知道这是一个非常古老的线程,但这是实现相同目的的 vbs 解决方案。只需将其放在 .vdproj 文件旁边的部署文件夹中即可。

Function CreateGuid()
    CreateGuid = Left(CreateObject("Scriptlet.TypeLib").Guid,38)
End Function

Const ForReading = 1, ForWriting = 2, ForAppending = 8

Set fso = CreateObject("Scripting.FileSystemObject")
Set RegEx = CreateObject("VBScript.RegExp")

For Each file in fso.GetFolder(".").Files
    if (fso.GetExtensionName(file.Name) = "vdproj") then
        WScript.Echo "Updating: " + file.Name
        Set oFile = fso.OpenTextFile(file.Name, ForReading, True)
        fileContents = oFile.ReadAll
        oFile.Close
        RegEx.Pattern = """ProductCode"" = ""8:{.*-.*-.*-.*-.*}"
        fileContents=Regex.Replace(fileContents, """ProductCode"" = ""8:" & CreateGuid)
        Set oFile = fso.OpenTextFile(file.Name, ForWriting, True)
        oFile.Write fileContents
        oFile.Close
    end if
Next

然后在你的真实项目中,有一个类似于以下的构建后事件:

cd $(SolutionDir)\CustomWebSetup
cscript -nologo UpdateProductCode.vbs

这将使用新的 ProductCode 更新 vdproj,为下一个构建做准备。构建完成后,VS会提示重新加载部署项目。

【讨论】:

    【解决方案2】:

    我知道最初的发帖人正在寻找解决此问题的 .NET 2.0 解决方案。然而,由于它没有被标记为 .NET,我将提供我的 C++ 解决方案来解决这个问题。这可能适用于 .NET 领域,但我将把它留给其他人。

    这不仅会更新我的应用程序的 about 框和日志文件中的版本信息,还会更新在 Windows 资源管理器中看到的所有 Windows 版本信息。

    更新:添加了自我最初回答以来我对流程所做的一些更改。

    首先,我将整个版本信息块从我的 Project.rc 文件移动到我的 Project.rc2 文件:

    /////////////////////////////////////////////////////////////////////////////
    //
    // Version
    //
    
    VS_VERSION_INFO VERSIONINFO
     FILEVERSION FILE_VER
     PRODUCTVERSION PROD_VER
     FILEFLAGSMASK 0x3fL
    #ifdef _DEBUG
      FILEFLAGS 0x1L
    #else
      FILEFLAGS 0x0L
    #endif
      FILEOS 0x4L
      FILETYPE 0x1L
      FILESUBTYPE 0x0L
    BEGIN
       BLOCK "StringFileInfo"
       BEGIN
           BLOCK "040904e4"
           BEGIN
               VALUE "CompanyName", "MyCompany"
               VALUE "FileDescription", "Software Description"
               VALUE "FileVersion", 1,0,0,1
               VALUE "InternalName", "FileName.exe"
               VALUE "LegalCopyright", "(c) 2008 My Company.  All rights reserved."
               VALUE "OriginalFilename", "FileName.exe"
               VALUE "ProductName", "Product Name"
               VALUE "ProductVersion", 1,0,0,1
           END
       END
       BLOCK "VarFileInfo"
       BEGIN
           VALUE "Translation", 0x409, 1252
       END
    END
    

    这实际上将您将从资源编辑器编辑的所有版本信息内容传输到一个单独的文件中。这使得您在从编辑器外部编辑资源文件时不会出错。缺点是您不能再从资源编辑器中编辑版本信息。但是,由于我们希望这些内容自动更新,这没什么大不了的。

    接下来,我创建了一个 VersionInfo.h 文件并将其添加到我的项目中:

    #pragma once
    
    //major release version of the program, increment only when major changes are made
    #define VER_MAJOR 2
    
    //minor release version of the program, increment if any new features are added
    #define VER_MINOR 0
    
    //any bugfix updates, no new features
    #define VER_REV 0
    
    //if this is some special release (e.g. Alpha 1) put the special release string here
    #define STR_SPECIAL_REL "Alpha 1"
    
    
    #define FILE_VER VER_MAJOR,VER_MINOR,VER_REV
    #define PROD_VER FILE_VER
    
    //these are special macros that convert numerical version tokens into string tokens
    //we can't use actual int and string types because they won't work in the RC files
    #define STRINGIZE2(x) #x
    #define STRINGIZE(x) STRINGIZE2(x)
    
    #define STR_FILE_VER STRINGIZE(VER_MAJOR) "." STRINGIZE(VER_MINOR) "." STRINGIZE(VER_REV)
    #define STR_PROD_VER STR_FILE_VER " " STR_SPECIAL_REL
    
    #define STR_COPYRIGHT_INFO "©" BuildYear " Your Company. All rights reserved."
    

    然后我将 VersionInfo.h 包含在 rc2 文件中并进行了以下更改:

    #include "VersionInfo.h"
    /////////////////////////////////////////////////////////////////////////////
    //
    // Version
    //
    
    <no changes>
               VALUE "FileVersion", STR_FILE_VER
               <no changes>
               VALUE "LegalCopyright", STR_COPYRIGHT_INFO
               <no changes>
               VALUE "ProductVersion", STR_PROD_VER
    <no changes>
    

    通过此设置,我可以在使用 devenv 命令行重新构建整个项目之前,编辑我的构建脚本(它使用 Perl)来修改 VersionInfo.h 文件中的版本信息。

    我添加的另一个步骤可能也很有趣(尽管它还没有完全完善,并且可能是未来的问题)是在每次构建项目时生成一个唯一的内部版本号。在当前版本中,它始终适用于完全重建,但仅偶尔适用于增量构建。我所做的是创建一个名为 build_number.incl 的文件,其中包含以下内容:

    #define CurrentBuildNumber  "20081020P1525" 
    

    本质上是构建开始的日期和时间。我创建了一个批处理文件,该文件作为生成此文件的项目的预构建事件运行。该脚本还定义了 BuildYear,以便 VersionInfo.h 文件中的版权始终包含最近构建的年份。批处理脚本如下:

        echo Generating Build Number
        @For /F "tokens=2,3,4 delims=/ " %%A in ('Date /t') do @(
        Set Month=%%A
        Set Day=%%B
        Set Year=%%C
        )
    
        @For /F "tokens=1,2,3 delims=/M: " %%A in ('Time /t') do @(
        Set Hour=%%A
        Set Minute=%%B
        Set AmPm=%%C
        )
    
        @echo #define CurrentBuildNumber  "%Year%%Month%%Day%%AmPm%%Hour%%Minute%" > "$(ProjectDir)\build_number.incl"
        @echo #define BuildYear "%Year%" >> "$(ProjectDir)\build_number.incl"
        echo ----------------------------------------------------------------------
    

    然后,此文件将包含在项目中需要使用内部版本号的任何文件中(即 about 框)。

    其中一些来自this CodeProject post.

    希望这些信息对您有所帮助。

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题,我发现修改 prebuildevent 中的 .vdproj 文件并不完全符合我的喜好。

      在安装项目构建完成后,我使用了一些其他代码修改了msi文件文件,因此我使用了postbuildevent

      请参阅我的博文here

      【讨论】:

      • 遇到了完全相同的问题。 VS 在运行 prebuild 步骤后不会重新加载 vdproj,因此需要构建两次,或者使用 postbuild 方法。
      【解决方案4】:

      Resource Tuner Console

      此控制台资源编辑器允许创建可靠且可重复的 最终版本更新产品版本信息资源的流程 从命令提示符进入构建过程的阶段。

      具体参见文件版本信息批量处理页面了解更多详情:

      【讨论】:

        【解决方案5】:

        研究 RCS、CVS 和/或颠覆的使用。我只熟悉RCS;我的理解是 CVS 基于 RCS 但更全面。我在各种板上读到颠覆更好,但我从未使用过它。 RCS 足以跟踪我所有文档和软件项目的更改和版本。

        RCS 在这里:http://www.cs.purdue.edu/homes/trinkle/RCS/

        CVS 在这里:http://www.nongnu.org/cvs/

        Subversion 在这里:http://subversion.tigris.org/

        【讨论】:

        • 我使用 git post-commit 钩子更新源代码的版本信息。
        【解决方案6】:

        我今天正在寻找完全相同的东西。我用谷歌找到了这个:

        static void Main(string[] args) 
        {
            string setupFileName = @"<Replace the path to vdproj file>"; 
            StreamReader reader = File.OpenText(setupFileName); 
            string file = string.Empty; 
        
            try 
            { 
                Regex expression = new Regex(@"(?:\""ProductCode\"" = 
                \""8.){([\d\w-]+)}"); 
                Regex expression1 = new Regex(@"(?:\""UpgradeCode\"" = 
                \""8.){([\d\w-]+)}"); 
                file = reader.ReadToEnd(); 
        
                file = expression.Replace(file, "\"ProductCode\" = \"8:{" + 
                Guid.NewGuid().ToString().ToUpper() + "}"); 
                file = expression1.Replace(file, "\"UpgradeCode\" = \"8:{" 
                + Guid.NewGuid().ToString().ToUpper() + "}"); 
            } 
            finally 
            { 
                // Close the file otherwise the compile may not work 
                reader.Close(); 
            } 
        
            TextWriter tw = new StreamWriter(setupFileName); 
            try 
            { 
                tw.Write(file); 
            } 
            finally 
            { 
                // close the stream 
                tw.Close(); 
            } 
         }
        

        【讨论】:

        • 我使用这种方法来更改我的 vsproj 上的产品代码,以便在构建和运行我的 msi 时 - 它可以很好地升级,而无需要求用户删除以前的版本。非常感谢,我一直在寻找如何做到这一点!
        • +1 我也有同样的问题,似乎正则表达式可能是最简单的解决方案。
        【解决方案7】:

        这可能不是您所追求的,但早在过去的迷雾中,我写了一个名为 stampver 的东西,它可以直接在 .exe 文件中自动增加内部版本号作为构建后步骤.

        【讨论】:

          【解决方案8】:

          我们使用基于配置文件值更新每个 AssemblyInfo.cs 或 AssemblyInfo.vb 的程序。我们在每次构建之前运行这个可执行文件。这是我们可以做的最好的自动化这个过程。您可以在项目配置中添加对此批处理过程的调用作为预构建步骤。

          【讨论】:

          • 这可以使用前置条件包含在构建过​​程中。
          【解决方案9】:

          Embedding SVN Revision number at compile time in a Windows app

          在我对这个问题的回答中,我描述了我是如何使用 SVN 完成这项任务的。

          【讨论】:

            【解决方案10】:

            您可以使用 msbuild 任务来更新您的产品版本。查看 MSBuild 团队关于此主题的 this post

            【讨论】:

            • 现在 (2012) AssemblyInfoTask 在哪里?
            猜你喜欢
            • 1970-01-01
            • 2015-09-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多