如何以编程方式更改项目的产品版本?

发布于 2024-07-08 21:15:29 字数 159 浏览 9 评论 0 原文

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

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

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

I have several deployment projects. In order to deploy an application, I need to do several tasks, one of them is to change each deployment project's product version and product code.

I can't find a way to programmatically change them.

Since it's a Deployment project (which finally produces an executable installer), I'm not able to work with MSBuild, instead I'm using the Devenv from the command prompt.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

野心澎湃 2024-07-15 21:15:29

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

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(); 
    } 
 }

I was searching for the exact same thing today. I found this using google:

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(); 
    } 
 }
ˇ宁静的妩媚 2024-07-15 21:15:29

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

这不仅会更新我的应用程序的“关于”框和日志文件中的版本信息,还会更新 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>

通过此设置,我可以编辑构建脚本(使用 Perl)来修改使用 devenv 命令行重建整个项目之前,请先查看 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 ----------------------------------------------------------------------

然后将该文件包含在项目中需要使用内部版本号的任何文件中(即“关于”框)。

其中一些内容是从这篇 CodeProject 帖子中收集的。

希望这些信息能够证明有帮助。

I know that the original poster is looking for a .NET 2.0 solution to this problem. However, since this wasn't tagged as .NET, I'll offer up my C++ solution to the problem. This may be applicable in .NET land, but I'll leave that to others.

This not only updates the version information in the about box and log file for my application, but also all of the Windows version info that is seen in Windows Explorer.

UPDATE: Added some changes that I've made to the process since my original answer.

First off, I moved the entire version info block from my Project.rc file to my Project.rc2 file:

/////////////////////////////////////////////////////////////////////////////
//
// 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

This essentially transports all of the version info stuff that you would edit from the resource editor into a separate file. This makes it so that you don't get errors when editing the resource file from outside of the editor. The downside is that you can no longer edit the version info from the resource editor. But, since we want this stuff updated automatically, that isn't a big deal.

Next, I created a VersionInfo.h file and added it to my project:

#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."

I then included VersionInfo.h in the rc2 file and made the following changes:

#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>

With this setup, I could edit my build script (which uses Perl) to modify the version info in the VersionInfo.h file before rebuilding the entire project using the devenv command line.

One additional step that I added that may also be of interest (although it is not completely perfected yet, and may be a future question here) is to generate a unique build number every time the project is built. In the current incarnation, it always works for complete rebuilds, but only sporadically on incremental builds. What I did was create a file called build_number.incl that contains the following:

#define CurrentBuildNumber  "20081020P1525" 

Which is essentially the date and time that the build was started. I created a batch file that is run as a pre-build event to the project that generates this file. The script also defines BuildYear so that the copyright in the VersionInfo.h file always contains the year of the most recent build. The batch script is the following:

    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 ----------------------------------------------------------------------

This file is then included in any file in the project that needs to use the build number (i.e. the about box).

Some of this was gleaned from this CodeProject post.

Hopefully this info proves helpful.

赠意 2024-07-15 21:15:29

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

We use a program that updates each AssemblyInfo.cs or AssemblyInfo.vb based on a configuration file value. we run this executable before each build. That was the best we could do to automate this process. You can add a call to this batch process in your projects configuration as a pre build step.

思慕 2024-07-15 21:15:29

我遇到了同样的问题,我发现修改 prebuildevent 中的 .vdproj 文件并不完全正确做我喜欢的事。

在构建安装项目后,我使用了一些其他代码来修改 msi 文件,因此我使用 postbuildevent< /强>。

请参阅我的博客文章此处

I had the same problem, and I found out that modifying the .vdproj file in a prebuildevent does not exactly do what I like.

I used some other code to modify the msi file file after the the setup project has been build, so I use the postbuildevent.

See my blog-post here.

め七分饶幸 2024-07-15 21:15:29

您可以使用 msbuild 任务来更新产品版本。 查看

You could use the msbuild task to update you product version. Check out this post from the MSBuild team on this subject.

温柔一刀 2024-07-15 21:15:29

在编译时嵌入 SVN 修订号Windows 应用程序

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

Embedding SVN Revision number at compile time in a Windows app

In my answer to this question, I describe how I accomplish this task using SVN.

娇妻 2024-07-15 21:15:29

这可能不是您所追求的,但早在时间的迷雾中我写了一些名为 stampver,它可以直接在 .exe 文件中自动递增构建号作为构建后步骤。

This may not be quite what you're after, but way back in the mists of time I wrote something called stampver, which can auto-increment a build number directly in the .exe file as a post-build step.

对你再特殊 2024-07-15 21:15:29

资源调节器控制台

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

具体请参阅文件版本信息的批量操作页面以获取更多详细信息:

Resource Tuner Console

This console resource editor allows creating a reliable and repeatable
process for updating Product Version Information resources during the final
stage of the build process from the command prompt.

See specifically the batch manipulation of file version information page for greater details:

笙痞 2024-07-15 21:15:29

我知道这是一个非常古老的线程,但这里有一个 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 将提示重新加载部署项目。

I know this a very old thread, but here's a vbs solution to achieve the same end. Simply place this in your deployment folder next to the .vdproj file.

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

Then in your real project, have a post build event similar to:

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

This will update the vdproj with a new ProductCode in preparation for the next build. After the build is complete, VS will prompt for a reload of the deployment project.

别挽留 2024-07-15 21:15:29

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

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

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

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

Look into the use of RCS, CVS and/or subversion. I am only familiar with RCS; my understanding is that CVS is based on RCS but more comprehensive. I have read on various boards that subversion is the better, but I have never used it. RCS has been adequate for keeping track of changes and versions on all my documents and software projects.

RCS is here: http://www.cs.purdue.edu/homes/trinkle/RCS/

CVS is here: http://www.nongnu.org/cvs/

Subversion is here: http://subversion.tigris.org/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文