我有几个部署项目。为了部署一个应用程序,我需要执行多个任务之一是更改每个部署项目的产品版本和产品代码。
我找不到以编程方式更改它们的方法。
由于这是一个部署项目(最终生成可执行安装程序),我无法使用MSBuild工作,而是在命令提示符中使用Devenv。
我有几个部署项目。为了部署一个应用程序,我需要执行多个任务之一是更改每个部署项目的产品版本和产品代码。
我找不到以编程方式更改它们的方法。
由于这是一个部署项目(最终生成可执行安装程序),我无法使用MSBuild工作,而是在命令提示符中使用Devenv。
今天我在搜索完全相同的事情。我使用谷歌找到了这个:
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();
}
}
我知道原帖作者正在寻找一个.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."
#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文章。
希望这些信息能够有所帮助。
prebuildevent
中修改.vdproj
文件并不能完全实现我的需求。因此我使用了其他代码,在安装程序项目构建后修改msi
文件,所以我使用了postbuildevent
。请参考我的博客文章这里。我知道这是一个非常老的帖子,但这里有一个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
这将更新vdproj,为下一次构建做准备。构建完成后,VS会提示重新加载部署项目。
这个控制台资源编辑器允许在命令提示符下创建一个可靠和可重复的过程,用于在构建过程的最后阶段更新产品版本信息资源。
具体请参见文件版本信息的批量操作页面以获取更多详细信息:
了解RCS、CVS和/或Subversion的使用。我只熟悉RCS;我的理解是,CVS基于RCS但更全面。我在各种论坛上读到Subversion更好,但我从未使用过。RCS已足以跟踪所有我的文档和软件项目的更改和版本。
RCS在这里:http://www.cs.purdue.edu/homes/trinkle/RCS/
CVS在这里:http://www.nongnu.org/cvs/
Subversion在这里:http://subversion.tigris.org/