版本控制构建






4.90/5 (226投票s)
一个Visual Studio插件和命令行实用程序,用于自动化.NET和VC++项目的版本控制

引言
当创建新项目时,Visual Studio会在其中生成一个AssemblyInfo文件。此文件包含AssemblyVersion
属性等。版本信息由四个整数值组成:主版本号、次版本号、内部版本号和修订号。Visual Studio 2002/2003生成的版本信息的默认模式是1.0.*,即主版本号设置为1,次版本号设置为0,而内部版本号和修订号是自动生成的。更具体地说,在构建过程中,内部版本号从2000年1月1日开始经过的天数计算,而修订号则从当天的本地当前时间计算。VB.NET项目和托管VC++项目也适用类似的规则,只是项目信息文件的名称分别为AssemblyInfo.vb和AssemblyInfo.cpp。
然而,这种自动化有时可能会令人烦恼。例如,如果您想为多个项目分配相同的版本。即使您重建同一解决方案中的所有项目,它们也可能获得不同的修订号。此外,如果您想从版本控制系统中重建旧的修订版本,您将不得不手动设置版本。
Visual Studio 2005默认生成格式为1.0.0.0的AssemblyVersion
属性(即版本中没有通配符),并且还添加了AssemblyFileVersion
属性。请注意,用户还可以包含分配给产品版本的AssemblyInformationalVersion
属性。
正如George Shepherd的Windows Forms FAQ (George Shepherd's Windows Forms FAQ) 所建议的,一个同步多个项目版本的简单方法是将版本信息提取到单个文件中,并从每个项目中引用它。然而,这种方法有一个缺点:如果一个程序集在不同的解决方案中使用,您最终可能会得到两个不同版本的相同程序集。
此插件的目的是帮助用户管理和同步所有这些版本,特别是对于包含多个项目的解决方案。Darriel Liu (Build Number Automation for Visual Studio .NET Projects) 已经提供了一个解决方案,他创建了一个Visual Basic宏来修改AssemblyVersion
,基本上遵循了Microsoft的原始方法。此解决方案用C#编写,扩展了原始的思路,提供了GUI以获得更多控制,并支持独立或同步管理所有三种版本类型。它还提供了一种自动化方法,以尽可能简化版本控制。
此外,插件还支持非托管项目中的Visual C++资源文件版本(FileVersion
和ProductVersion
)以及设置项目版本。
最后但同样重要的是,命令行实用程序不仅提供了插件的批量对应功能,还将其功能扩展到了Visual C++ 6.0项目。
本文首先提供有关版本的基本信息以及此工具如何管理版本。接下来是实现细节,包括对所用特定技术的描述。熟悉版本控制且不感兴趣于实现细节的读者可以跳到最后一部分,其中提供了用户基本说明。
目录
背景
本节将更详细地介绍.NET Framework中的版本,并描述本工具使用的逻辑。
三个版本守护者
如引言中已提及,.NET Framework支持三种类型的版本:AssemblyVersion
、AssemblyFileVersion
和AssemblyInformationalVersion
,分别对应AssemblyVersionAttribute
、AssemblyFileVersionAttribute
和AssemblyInformationalAttribute
。属性的实际值定义在AssemblyInfo文件中(Visual Studio 2005及更高版本将此文件隐藏在Properties子文件夹中)。
// ...
[assembly: AssemblyVersion("1.1.*")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.2.1.0")]
// ...
请注意,给出的示例内容是C#AssemblyInfo文件;对于其他语言,语法略有不同。
正如读者可能知道的,AssemblyVersion
存储在构建程序集的元数据表中。当其他程序集引用它时,它用于唯一标识一个程序集。此外,CLR在绑定到强命名程序集时使用此版本(更多细节可以在Jeff Richter的书《Applied Microsoft .NET Framework Programming》中找到)。AssemblyFileVersion
和AssemblyInformationalVersion
仅供参考(参见例如"如何使用程序集版本和程序集文件版本"和"程序集版本控制"文章)。然而,值得注意的是,Windows Installer在将一个文件安装到已存在同名文件位置时会使用AssemblyFileVersion
(参见"文件版本规则"文章 - 感谢si618的指出)。
这些值被合并到程序集中,并在编译后的程序集属性窗口的版本选项卡上显示。

窗格顶部显示的文件版本对应于AssemblyFileVersion
属性,而其他两个属性显示在“其他版本信息”组合框内。如果AssemblyInfo文件中缺少任何属性,则会分配另一个可用属性的值。例如,如果只定义了AssemblyVersion
属性,那么它的值将被用于文件版本和产品版本。如果未定义任何版本,则默认为0.0.0.0
。
如果在.NET Framework文档中检查AssemblyVersionAttribute
、AssemblyFileVersionAttribute
和AssemblyInformationalAttribute
类的描述,您可能会注意到它们每个都有一个Version
属性(在AssemblyInformationalVersionAttribute
类中,该属性名为InformationalVersion
)。此属性是一个字符串,这意味着它可以包含任何有效的字符串,并且不受限于点分隔的四个整数列表。但是,如果您尝试将版本字符串更改为其他形式,编译器会发出警告或错误。至少必须提供一个整数(即主版本号)。因此,以下字符串是有效版本:
1
1.2
1.2.3
1.2.3.4
单个星号只能在AssemblyVersion
中用作内部版本和修订号,或仅用作修订号的通配符。
1.2.*
1.2.3.*
有趣的是,虽然.NET Framework中有一个名为Version
的类用于表示程序集版本,但上述任何版本类均不使用它。
C++资源文件中的版本
尽管对于托管C++项目,会创建一个AssemblyInfo.cpp文件(带有AssemblyVersion
值),但其内容不会显示在已编译代码的属性中。对于非托管C++应用程序,则使用资源文件(*.rc)来存储版本信息。
// ...
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
// ...
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "041a04b0"
BEGIN
// ...
VALUE "FileVersion", "1, 0, 0, 1"
// ...
VALUE "ProductVersion", "1, 0, 0, 1"
END
END
// ...
END
正如您所见,文件版本和产品版本至少出现两次:在VS_VERSION_INFO
块下方,以及在StringFileInfo
块内。此外,StringFileInfo
块可能包含多个块,每个块对应一种不同的语言。另请注意,版本的 Separator 可能因本地化设置而异。
需要指出的是,对于托管C++项目,版本信息块不会自动在资源文件中生成,但开发者必须添加它,例如在Resource View窗口中,或手动编辑资源文件的内容。
设置项目中的版本
与其他项目类型不同,设置项目只有产品版本。它可以包含最多三个点分隔的整数,并存储在项目文件(扩展名为.vdproj)本身中(而不是单独的文件中)。
// ...
"Product"
{
"Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:SetupProject"
"ProductCode" = "8:{1DC3B403-8041-43BD-BA39-588EDA4325E4}"
"PackageCode" = "8:{C2627176-ED8C-40B0-B9E2-095D4612A21C}"
"UpgradeCode" = "8:{1FD6C202-4297-4AAE-8C48-DDB81C44EC44}"
// ...
"ProductVersion" = "8:2.0.0"
// ...
}
您可能会注意到,数字8后跟着一个冒号 precedes the Product Version value。这个数字仅指示要跟随的数据类型(8代表字符串)。
当在Visual Studio环境中修改设置产品的版本时,系统会要求您修改ProductCode
和PackageCode
。这些代码(以GUID形式给出)用于在后续安装或升级过程中标识应用程序。因此,修改产品版本的工具应能够为这两种代码创建新的GUID。
本工具使用的逻辑
AssemblyInfo文件通常在创建项目时首次修改:开发者输入公司名称、版权和产品描述等信息。之后,它很少被修改,通常只是为了更改版本信息。因此,当源代码在版本更改后被修改时,“文件已修改”的时间戳将比AssemblyInfo文件的时间戳更新。
当用户从四个命令之一启动工具时,该工具会浏览当前打开的解决方案中的项目。对于C#、VB.NET、VJ#或VC++项目中的每个文件,将比较文件最后保存的时间戳与相应AssemblyInfo文件的时间戳。如果存在时间戳更新的文件(意味着源代码在上次版本更改后被修改),则该项目将被标记为待版本更新。在GUI中,项目将在主应用程序窗体中显示一个复选标记,并显示下一个建议版本,该版本根据工具设置创建。用户可以更改选择,甚至修改下一个版本。从窗体触发构建后,应用程序将更新所有选定项目的程序集版本并(重新)构建解决方案。批量命令在没有用户干预的情况下执行相同的过程。
根据配置设置,该工具还将Visual C++资源文件(可能包含ProductVersion
和FileVersion
)包含在编号方案中:如果资源文件包含版本信息,则将其时间戳与项目中的所有文件的时间戳进行比较。如果项目(例如,托管C++应用程序)同时在AssemblyInfo和资源文件中包含版本信息,则使用较大的版本作为参考。
需要指出的是,如果Visual C++项目包含资源文件但没有AssemblyInfo文件,添加新资源时通常会将最新时间戳放在资源文件上,项目将不会被标记为版本更新。然而,值得注意的是,添加新资源通常会修改resource.h头文件,该文件在资源文件之前保存。因此,为了(至少部分)规避上述不一致,参考时间戳(用于与其他项目文件的时间戳进行比较)是从资源文件时间戳偏移一秒生成的。
由于设置项目由单个文件组成,因此无法为此实现时间戳比较逻辑——用户必须手动选择这些文件进行版本更新。
使用演示项目
下载的演示项目是一个VS2008解决方案,由几个不同的项目组成。
- Addin项目,只包含一个类,该类实现了
IDTExtensibility2
和IDTCommandTarget
接口以创建插件。此类是通过注册表注册的插件的公共入口点(即COM对象注册),因此只需要注册一个类。 - Implementation项目是实现插件功能的主模块。
- Buttons是包含用于工具栏按钮和菜单的图像的资源DLL。
- CommandLine是命令行实用程序的主项目。
- Configurator项目用于将配置对话框作为独立应用程序启动。
- Shared项目包含插件和命令行实用程序共用的类。
- Test应用程序,可用于在安装为插件之前测试该应用程序。
- Setup,用于创建工具的安装程序。
最初,该解决方案是为.NET Framework 1.x在VS2002上创建的。随着插件版本2.0,添加了对VS2005的支持,后来扩展到最新的Visual Studio版本,如工具历史所述。为多个Visual Studio版本创建插件需要进行一些重新安排(如下文迁移到.NET 2.0部分所述),并且项目Implementation被复制(ImplementationVS7、ImplementationVS8和ImplementationVS9)以构建新环境的插件。请注意,所有Implementation项目共享相同的源代码,使用条件编译来区分特定于不同环境的代码部分。
该插件最初使用永久命令栏。永久命令栏仅在首次安装插件后运行Visual Studio时创建一次,并且Visual Studio会在会话之间保存它们的位置。此外,插件命令的按钮和菜单项可以自由地复制和移动到其他工具栏/菜单。另一方面,临时命令栏每次启动Visual Studio时创建,每次关闭Visual Studio时销毁。插件必须负责保存临时工具栏和菜单的位置及其布局。
由于某些第三方插件导致VCB菜单和工具栏在每次运行Visual Studio时都会出现重复,因此添加了带有临时栏(ImplementationVSxTemporaryBars)的额外实现项目和相应的Setup。实现项目共享大部分代码,因此它们包含相同的源文件。
兴趣点
项目中最大的挑战是利用VS.NET环境自动化,因为它文档很少且难以调试。此外,还采用了几个自定义控件和独特解决方案。其中一些将在以下各节中介绍。
连接到Visual Studio环境
该插件通过Connect
类与Visual Studio环境建立连接,该类的骨架由Add-in Wizard自动生成。该类以下方法用于:
OnConnection
:
- 接收应用程序对象的引用,该对象实际上是Visual Studio环境(
EnvDTE
)对象,并将其存储供工具进一步使用。 - 从VS环境选择当前线程的UI文化(用于可选的资源本地化)并加载相应的本地化资源。
- 为插件创建工具栏和菜单。
- 存储Build和Cancel Build命令的引用,用于动态启用或禁用插件工具命令。
OnDisconnection
:存储当前配置并移除工具栏和菜单栏。OnStartupComplete
:更新插件命令的状态。QueryStatus
:禁用和启用插件命令(以Build和Cancel Build命令的状态为参考);例如,当没有打开的解决方案或VS环境正在编译或构建时,插件将被禁用。Exec
:打开GUI或执行其中一个批量命令。
SolutionBrowser类
抽象类SolutionBrowser
是“主力”VSSolutionBrowser
、VS7SlnFileReader
、VS8SlnFileReader
和DswFileReader
类的基类,它们管理项目信息。VSSolutionBrowser
用于插件,并利用Visual Studio .NET自动化来浏览解决方案并收集所有包含的项目信息。它处理项目信息,例如所有与版本更新相关的项目项、文件保存时间比较和VS环境设置。命令行实用程序的对应项(VS7SlnFileReader
、VS8SlnFileReader
和DswFileReader
)通过解析相应的解决方案(*.sln或*.dsw)文件以及包含的项目文件来完成相同的工作。
在工具启动时,SolutionBrowser
派生类会浏览选定的解决方案,并收集每个项目的信息:项目类型、存储版本的AssemblyInfo(以及可选的*.rc和*.vdproj)文件的完整名称(包括路径)、所有版本类型的当前值以及一个指示项目自上次版本更新以来是否已被修改的标志。
AssemblyVersions
类包含一组ProjectVersion
,每个ProjectVersion
代表一种版本类型。ProjectVersion
能够比较和递增版本,以及应用带有通配符的字符串模式。ProjectInfo
类包含实际显示在ListView
中的项目信息。AssemblyInfoStream
、ResourceFileStream
和SetupVersionStream
类派生自抽象类VersionStream
,并负责在相应文件中检索和存储版本。
主窗体
MainForm
类代表主窗口,包含三个带有标签页的ProjectsListView
(派生自ListView
类),显示所有项目及其当前和下一个建议版本,每个版本类型一个列表视图。为避免TabControl在调整大小时出现众所周知的闪烁问题,使用了派生自UserControl
的控件。
主窗口在ProjectsListView
的右侧包含几个按钮,用于管理项目选择,以及用于触发保存和构建操作的按钮。它还包含一个VersionUpDown
编辑框,用户可以在其中手动定义要应用于选定项目的新版本模式。
ProjectsListView
ProjectsListView
是一个自定义绘制的列表视图控件。自定义绘制是必需的,以允许动态更改项的外观:项根据版本可用性和有效性以不同颜色显示,或者在项未选中时显示为灰色。通过实现文章"Flicker-free ListView in .NET - Part 2"中描述的技术,减少了过度的闪烁。
一个派生自TextBox
的控件嵌入到ProjectsListView
中,以允许“待版本”的行内编辑,如"In-place editing of ListView subitems"文章中所述。需要注意的是,嵌入的TextBox
的Multiline
属性默认为false
,它有一个有限的最小尺寸。此尺寸大于列表视图单元格的尺寸,这使得行内编辑控件的外观显得笨拙。为了解决这个问题,EmbeddedTextBox
被设置为多行,并且重写了OnKeyPress
方法以捕获Enter键并避免跳到下一行。
ProjectsListView
还重写了OnItemCheck
方法,以防止选中无效版本的项。
VersionTextBox
VersionUpDown
控件是一个用户控件,由两个控件组成:VersionTextBox
和SpinButton
。VersionTextBox
是一个控件,它对用户进行限制,即输入版本时,只能使用由点分隔的四个整数、星号或加号字符的序列。SpinButton
派生自VScrollBar
类。
VersionTextBox
派生自TextBox
,并重写了一些事件处理程序以确保特定行为。必须重写OnKeyPress
以防止用户输入数字或星号以外的任何内容。此外,版本序列的四个部分被虚拟地分成四个块,每个块都有自己的Tab停止。为了实现这一点,必须重写PreProcessMessage
方法以处理TAB、HOME、END、BACKSPACE、DELETE和箭头键。
为了使内部制表符顺序与对话框制表符顺序同步(当对话框中的下一个控件被后退制表时,必须选择最后一个块),定义了两个委托实例并将其添加到Next和Previous控件的LostFocus
事件中。
override protected void OnParentVisibleChanged(EventArgs e)
{
base.OnParentVisibleChanged(e);
if (TopLevelControl != null)
{
Control nextControl = GetNextTabControl(Parent, true);
if (nextControl != null)
nextControl.LostFocus += new System.EventHandler(
OnNextControlLostFocus);
Control previousControl = GetNextTabControl(Parent, false);
if (previousControl != null)
previousControl.LostFocus += new System.EventHandler(
OnPreviousControlLostFocus);
}
}
// searches for the next control that has a tab stop
private Control GetNextTabControl(Control ctl, bool forward)
{
do
{
ctl = TopLevelControl.GetNextControl(ctl, forward);
if (ctl == null || ctl == this)
return null;
}
while (ctl.TabStop == false);
return ctl;
}
// selects the last block
private void OnNextControlLostFocus(object sender, EventArgs e)
{
SelectionStart = Text.Length - 1;
}
// selects the first block
private void OnPreviousControlLostFocus(object sender, EventArgs e)
{
SelectionStart = 0;
}
为了防止选择范围跨越分隔点,有必要重写OnMouseDown
、OnMouseMove
和OnMouseUp
事件处理程序。此外,通过重写WndProc
方法,将“全选”命令限制为单个块,同时禁用了上下文菜单、撤销操作以及所有与剪贴板相关的操作。
其他相关类
WindowAdapter
类用于当MainForm
和PromptUnsavedDocumentsDialog
作为模态窗体显示时,将VS环境主窗口作为它们的父窗口。PromptUnsavedDocumentsDialog
模仿如果“项目和解决方案”页面上的“构建和运行选项”设置为“提示保存更改...”时弹出的对话框。即,为了防止在插件已启动时弹出此对话框(从而阻塞其执行),应用程序将首先检查未保存的文档,然后(如果需要)弹出PromptUnsavedDocumentsDialog
,最后暂时禁用保存打开的文档。
MessageFilter
类用于处理“应用程序正忙”和“被调用者拒绝调用”错误,这些错误在调用Visual Studio自动化时经常出现,并可能阻止插件启动(请参阅"Fixing 'Application is Busy' and 'Call was Rejected By Callee' Errors"文章)。
AssemblyInfoStream
、ResourceFileStream
和SetupVersionStream
类(派生自抽象类VersionStream
)用于读取当前版本并保存新版本。正则表达式用于定位、提取和保存新版本。
迁移到.NET 2.0
.NET 2.0中,Framework类库发生了一些变化。例如,命令栏已从Microsoft.Office
移至Microsoft.VisualStudio.CommandBars
程序集,并且推荐使用EnvDTE80.DTE2
而不是旧的EnvDTE.DTE
类。尽管所用类的功能没有显著改变(大部分都得到了扩展),但一些类被移至新的Framework程序集中,这使得以前版本的插件在没有代码修改的情况下对于新IDE将不再有用。
由于插件的功能在.NET Framework更改后保持不变,因此可以通过对源代码进行少量修改并更新对.NET Framework程序集的引用来简单地重新编译代码。但采用这种方法,将失去与以前版本的VS IDE的兼容性。为了使源代码与以前的.NET Frameworks兼容,已在必要的地方插入了条件编译语句。
#if VS8
using EnvDTE80;
using DTE = EnvDTE80.DTE2;
#endif
在所有除了一个情况之外,插入
使用以下条件预处理器指令解决了命令栏定义在不同程序集中的问题。
#if VS7
using Microsoft.Office.Core;
#elif VS8
using Microsoft.VisualStudio.CommandBars;
#endif
为了从同一源代码生成两个不同的程序集,复制了相应的项目文件,两个项目包含完全相同的源代码,但定义了不同的条件编译常量(VS 200x的VS7
和VS 2005/2008的VS8
)并引用了不同的.NET Framework程序集。当然,为了区分版本,输出被命名为不同:BuildAutoIncrementVS7和BuildAutoIncrementVS8。
为了使用一个安装集并为所有IDE版本提供单个插件注册,代码被分成两部分:一部分是两个Framework版本共有的,另一部分是每个版本特有的。通用的启动代码检测当前激活的Framework,并加载相应的核心程序集。通过使用反射,在该程序集中搜索实现IAddin
接口的核心类,并创建该类的实例。IAddin
接口定义在Common程序集中。下面提供了一个简化的代码:
int runtimeVersion = Environment.Version.Major;
Assembly assembly;
switch (runtimeVersion)
{
case 1:
assembly = Assembly.Load("BuildAutoIncrementVS7");
break;
case 2:
assembly = Assembly.Load("BuildAutoIncrementVS8");
break;
default:
return;
}
// in the main assembly find the type that implements IAddin
// interface and create an instance of it
Type[] types = assembly.GetTypes();
foreach (Type type in types)
{
if (type.IsClass)
{
if (type.GetInterface("IAddin", true) != null)
{
ConstructorInfo ci = type.GetConstructor(Type.EmptyTypes);
m_addin = (IAddin)ci.Invoke(new object[0]);
}
}
}
启动模块中的方法仅将调用转发给核心实现类中相应的方法。
SourceSafe下的文件
该应用程序还能处理SourceSafe控制下的代码:如果需要,它会自动检出项目。然而,要充分利用这种自动化,请注意SourceSafe必须配置为在检出时将本地文件的时间和日期设置为修改日期和时间(参见下图),而不是默认的“当前”值。

另外,建议您在Visual Studio的“项目和解决方案”页面的“源代码管理”类别下的“选项”对话框中设置“检入项被编辑时”为“自动检出”。否则,每次都会提示您手动检出项目。此外,在这种情况下,从代码中检出项目非常棘手,因为对以下方法的调用会失败:
public static bool CheckOutItem(string fileName, DTE dte)
{
if (dte.SourceControl.IsItemUnderSCC(fileName) &&
!dte.SourceControl.IsItemCheckedOut(fileName))
return dte.SourceControl.CheckOutItem(fileName);
return true;
}
为避免这种情况,实现了Catalin Stavaru提供的思路:以编程方式选择VS环境的Solution Browser中的项,然后发出检出命令。感兴趣的读者可以在SolutionExplorerCheckoutHelper
类中找到实现细节。
使用加载项
安装后,将添加一个名为**VCB**的菜单以及一个新的**Versioning Controlled Build**工具栏(参见下图)。它们包含四个项目,如下所述:

- **Versioning Controlled Build**将打开一个窗口,如本文顶部所示。已准备好进行版本更新的项目会自动选中,但用户可以按其意愿修改版本。
- **Build with Versions Updated**将新版本应用于已修改的项目并触发Build Solution命令。
- **Rebuild with Versions Updated**将新版本应用于已修改的项目并触发Rebuild Solution命令。
- **Save Updated Versions**将首先保存所有已修改的文件,然后保存已修改项目的版本。
根据VS环境中“构建和运行选项”(“选项” - “环境” - “项目和解决方案”)中的选择,操作1、2和3将首先保存所有当前打开的文件。用户可以为上述任何操作分配快捷键(这是许多用户的要求)。
此外,VCB菜单包含四个额外的条目:
- **Save Versions**将当前版本导出到文件。
- **Print Versions**打印当前版本。
- **Configure**启动配置对话框。
- **About**弹出信息框。
GUI
启动GUI命令时,插件会浏览当前打开的解决方案中的所有项目,并显示它们当前的可用版本。它还会根据工具设置中定义的增量方案建议下一个版本。已检测到代码更改的项目将显示为绿色,并自动标记为更新。未检测到代码更改或未找到有效版本信息的项目最初将显示为灰色。
版本显示在三个带有标签页的列表视图上,每个列表视图对应一种版本类型:AssemblyVersion
、AssemblyFileVersion
(即FileVersion
)和AssemblyInformationalVersion
(即ProductVersion
)。可以通过单击列表视图上方的相应按钮或使用Ctrl+Tab组合键切换标签页。
用户可以根据需要选中/取消选中项目(只有具有有效版本的项目才能被选中)——所有命令将仅应用于选中的项目。请注意,根据配置设置,可能会出现一个项目在一个列表视图中被选中而在另一个列表中未被选中——在这种情况下,只有选中的版本会被处理。
通过“Apply to all tabs”复选框,用户可以控制GUI命令是分发到所有列表视图(即所有版本标签页)还是仅应用于当前可见的列表视图。它会覆盖工具配置中的类似设置。
应用版本模式
列表视图下方的文本框包含一个模式,可以应用于列表中选中的项目。在插件启动时,此文本框包含建议的最大“待版本”。但是,用户可以将其更改为任何有效版本。此外,可以在模式中使用星号(*)或加号(+)字符,后跟可选的整数。任何版本位置(主版本号、次版本号、内部版本号或修订号)上的星号都会阻止该位置被修改。这可能很有用,例如,当用户想同时递增多个或所有项目的次版本号,但保持各个内部版本号和修订号不变时。加号字符会将相应版本位置的整数递增指定值,如果没有提供整数,则递增1。例如,“1.0.*.+2”模式将主版本号和次版本号分别设置为1和0,保持内部版本号不变,并将修订号递增2。
当修改文本框中的内容时,列表视图中的版本将与版本模式进行比较。如果模式可能导致版本低于项目的当前版本,则项目将显示为红色,作为对用户的视觉警告。
按下“Apply”按钮后,文本框中的模式将应用于列表视图中所有选中的项目。请注意,实际文件中的版本在用户单击“command”按钮之一之前不会更改,如下面的“应用更改”子部分所述。
增加主版本号、次版本号、内部版本号或修订号
提供一组四个按钮,仅用于递增标记项目的版本组件之一。其他版本组件不会被修改,除非如此配置(参见下面的设置部分)。主版本更改时,次版本组件始终重置为0。
手动修改版本
对于现有版本,可以手动编辑建议的版本:只需单击“待版本”列中的版本,或选择相应项并按F2键。新版本将被验证,并且只允许具有至少两个点分隔整数和可选星号的版本。
应用更改
需要指出的是,新版本在单击“Save”、“Build”或“Rebuild”按钮之前不会实际保存。Save按钮仅将新版本保存到相应的文件中,而Build和Rebuild按钮还会额外向Visual Studio环境发出相应的命令。
批处理命令
批处理命令相当于GUI中的Save、Build和Rebuild All命令,只是它们会立即执行,无需用户干预。项目版本将根据工具的设置自动递增,如下所述。
命令行实用程序
命令行实用程序支持VC++ 6.0 DSW文件以及VS2002/2003/2005/2008/2010/2012/2013 SLN文件。它与插件版本共享配置设置,但用户可以使用适当的启动开关覆盖这些设置。请查看安装程序中包含的CommandLine.txt文件以获取简要描述和启动开关列表。
在命令行实用程序安装过程中,将在“Programs”菜单中添加相应的菜单,其中包含两个条目。“AutoVer”条目使用/g
开关启动命令行实用程序,打开与插件相同的GUI。
配置
设置存储在用户ApplicationData文件夹中的Configuration.xml文件中。此文件还存储主窗体的大小和列表视图中列的宽度。当用户在安装工具后首次启动Visual Studio时,会创建一个具有默认值的配置文件。由于它创建在用户配置文件中,因此每个用户都可以独立配置该工具。
设置对话框包含四个选项卡页,将在以下各节中介绍。
常规

在“General”选项卡页上,用户可以选择在主窗体上启动时显示哪个版本(AssemblyVersion
、AssemblyFileVersion
或AssemblyInformationalVersion
)。此外,此默认版本将是工具栏和菜单栏上的最后三个按钮或菜单项对应的“batch”命令所处理的版本。如果选中“Apply changes to all version types”,所有版本类型将独立处理,除非选中“For each project synchronize all version types”。通过“Allow arbitrary Informational Version”,用户可以手动输入自由格式文本(不符合文章开头中描述的版本模式)到相应的列表视图条目中,如手动修改版本子部分所述。“Include VC++ resource files”包括处理相应.RC文件中包含的ProductVersion
和FileVersion
。
要将Visual Studio设置项目包含在处理中,必须选中“Include setup projects”选项。还有一个选项可以在修改设置项目版本时自动生成新的ProductCode
和PackageCode
。
再次重申,由于设置项目由单个.vdproj文件组成,因此无法检查任何更改,用户必须手动标记设置项目以进行版本更改。
编号方案

“Numbering scheme”选项卡允许用户微调自动编号方案。选择“By default, increment:”选项,用户可以选择哪个版本部分由系统自动递增。这对于那些更喜欢将星号用于内部版本号和修订号(如Microsoft最初提出的)而只递增次版本号的人来说可能很有用:内部版本号和修订号的星号掩码将保持不变(除非用户选择下面的“Reset...”选项之一)。
当选中“Date & time based Build and Revision numbering”选项时,将使用本文开头提到的日期和时间规则来生成内部版本号和修订号的版本数字,并插入实际整数而不是星号。数字在工具启动时根据当前的本地日期和时间生成。
重置选项提供了对主版本号、次版本号或内部版本号递增时较不显著数字的控制。请注意,主版本号递增时,次版本号始终重置。
如果“Replace asterisk with component values”未被选中,版本中的星号将不会被整数值替换。
外观

此选项卡允许用户修改一些显示选项:用于突出显示列表视图项的着色方案以及项在列表视图中的外观。对于颜色选择,使用了 elsewhere中介绍的单独控件。
批处理命令

Batch Commands选项卡提供了对批处理命令的额外控制。用户还可以抑制执行批量命令时显示的报告对话框。
文件夹

此选项卡包含SourceSafe命令行(VCB命令行实用程序需要)的路径以及IIS根文件夹的路径。这些值通常在VCB安装时检测到,因此用户无需修改它们。
导出

此选项卡包含打印版本和导出到文件的设置。可以选择导出版本和导出顺序,定义缩进深度(导出到文件时的字符数或打印时的行高)。还可以为打印机输出选择字体。对于CSV文件输出,可以选择分隔符;根据本地化设置,逗号字符并不总是被识别为分隔符。
安装说明
如果您已安装此工具的任何先前版本,建议先卸载它。
对于所有Visual Studio版本(即2003、2005、2008、2010、2012和2013),都有独立的安装程序:一个用于带有永久命令栏的插件(BuildAutoIncrement.msi),另一个用于带有临时命令栏的插件(BuildAutoIncrementTemporaryBars.msi)。
插件无法安装在Visual Studio的Express版本上,因为它们不允许插件。命令行工具没有先决条件,除了必须安装.NET 2.0或更高版本。
鸣谢
我要感谢Don Bailes、Carl Mercier、David Smith以及许多其他人测试此插件并帮助我修复错误。
历史
- 版本 1.0
- 初始发布(于2004年1月15日发布)。
- 版本 1.1
- 支持VB.NET项目,并在UI中进行了一些美化更改。请注意,此版本的安装程序将自动移除之前的版本。
- 版本 1.2
- 添加了对托管VC项目 else 语言的支持,文本编码设置为默认值(启用扩展字符的使用),添加了
MessageFilter
以处理经常阻止应用程序的COM消息,还会显示缺少AssemblyInfo文件的项目,添加了用于递增选定项目的主版本号、次版本号或内部版本号的按钮(默认情况下始终递增修订号),并添加了仅保存更新的AssemblyInfo文件的Save按钮。
- 添加了对托管VC项目 else 语言的支持,文本编码设置为默认值(启用扩展字符的使用),添加了
- 版本 1.3
- 添加了设置对话框,设置在会话之间保存(参见上面的“设置”部分),并进行了一些错误修复。
- 版本 1.4
- 直接构建项目,额外的工具栏/菜单,以及对VJ#以及VB和C#智能设备项目 else 语言的支持。更健壮地支持在SourceSafe下检出文件。项目已准备好本地化。希望能修复插件在本地化版本的Visual Studio上无法运行的问题。
- 版本 1.5
- 修复了“Enterprise Template Project versions not processed”错误,添加了对资源文件(参见“设置”部分)中版本控制的支持。
- 版本 1.6
- 修复了“Database project bug”,通过修复“Disappearing icons”错误,改进了安装/卸载。
- 版本 1.7
- 修复了“SourceSafe checkout bug”和“Odd cosmetic bug”(如normanr所指出的)。
- 版本 1.8
- 修复了“AssemblyInformationalVersion bug”以及包含资源和AssemblyInfo文件的Visual C++项目检出问题。
- 版本 1.9
- 修复了版本 1.8引入的“Enterprise Templates Subprojects not shown”错误。
- 版本 2.0
- 支持VS 2005(请注意,该插件仅在VS 2005的beta 2版本上进行了测试;我还没有机会在IDE的发布版本上测试该插件)。设置中添加了附加选项,用于选择默认递增的版本部分。次要错误修复。重新组织了解决方案,以允许VS 2002/2003和VS 2005同时构建。
- 版本 2.1
- 修复了2.0版本的安装问题,为
AssemblyVersion
、AssemblyFileVersion
和AssemblyInformationalVersion
(即产品版本)添加了单独的标签页。**注意**:此版本与VS2002/2003和VS2005兼容。但是,在某些情况下,VS 2005工具栏/菜单上的图标由于未知原因可能不会显示。
- 修复了2.0版本的安装问题,为
- 版本 2.2
- 代码重构,次要错误修复(例如版本字符串周围的空格问题),GUI的微小更改(标签式列表视图之间的滚动位置同步,突出显示颜色配置),实现了“待版本”的行内编辑,为批处理命令添加了报告对话框,并添加了对设置项目 else 语言的支持。
- 版本 2.3
- 修复了Solution folders not displayed 错误;安装包已拆分(有一个适用于VS2002/2003/2005的安装程序,以及一个适用于仅有VS2005的系统的单独安装程序);工具栏/菜单已永久化,因此用户可以修改相应的图标(如果它们未在VS2005中显示);列表视图中的项目以与Solution Explorer相同的顺序显示(设置项目放在最后);解决方案文件夹和Enterprise Templates中的项目可以缩进显示(如Setup对话框的Appearance选项卡中所选)。已知问题:与某些第三方插件冲突。
- 版本 2.4
- 命令行实用程序,支持VC++ 6.0 DSW文件以及VS2002/2003/2005 SLN文件包含在安装程序中(请查看CommandLine.txt文件以获取简要描述);
- 进行了一些代码重组和重构,以及一些次要的错误修复。
- 版本 2.5
- 修复了命令行实用程序无法识别项目名称中包含非字母数字字符的项目的错误。还进行了一些其他次要的错误修复。
- 版本 3.0
- 代码重构,修复了一些错误并实现了一些新功能(我没有在Vista上测试该工具,所以请检查Vista和Vista RC2消息以获取安装问题)。
- 插件可以安装在Visual Studio 2008(beta2)上,命令行实用程序可以与Visual Studio 2008项目一起使用。
- 修复了在VS2005进行修复过程后按钮和菜单项倍增的错误。
- 修复了无效路径错误;这也能解决网络共享上的项目问题。
- 现在可以正确处理解决方案文件夹中的设置项目。
- 修复了Web项目版本未显示的错误。它也应该在命令行实用程序中工作。首次启动时,实用程序会检查IIS是否已安装,并应自动获取相应的根文件夹。此文件夹显示在设置对话框的“Folders”选项卡中,但可以手动修改。
- 修复了SourceSafe命令行无效路径的错误。此外,此路径可以在设置对话框的“Folders”选项卡中手动设置。
- 在配置(“Numbering Scheme”选项卡)中添加了从1重新启动Build和Revision的选项。
- 在配置(“General”选项卡)中添加了在插件命令启动前保存所有文件的选项。
- 如果C++项目的资源(*.rc)文件中的
FileVersion
和ProductVersion
不包含所有组件(Major.Minor.Build.Revision),则只有.RC文件中存在的组件会被更新。 - 如果C++项目包含多个带有版本字符串的资源(*.rc)文件,则所有文件中的版本都会被更新。
- 在配置(“Numbering Scheme”选项卡)中添加了定义版本递增步长的选项。
- 选项以输入AssemblyInformationalVersion(即非C++项目的产品版本)的任意文本(“General”选项卡)。此选项也可与命令行实用程序一起使用。
- 现在可以通过在GUI的“To Version”框前加上“+”字符来输入任何版本增量,例如,“1.0.0.+10”(将当前修订号递增10)。
- 命令行实用程序已完成。请查看实用程序附带的CommandLine.txt用户指南以获取详细信息。请注意,已修改/重命名了几个命令行开关。
- 版本 3.1
- 添加了打印当前版本或将其保存到文本/CSV文件的选项,现在支持Windows视觉样式,并进行了一些错误修复。
注意:如果您在安装了VS 2008的系统上安装了VS2005/2008的3.0版本,由于其安装中的一个错误,您需要按照以下步骤操作:- 首先卸载先前版本
- 检查VS2008命令提示符下是否仍然存在**命令**(非工具栏/菜单):*Tools* - *Customize* - *Commands*选项卡,在*Categories*列表中选择*Addins*,并查看它是否包含
GUI
、Build
、Rebuild
、Save
、Configure
和About
条目。如果其中任何一个存在,请从Visual Studio 2008命令提示符运行以下命令:
devenv /resetaddin BuildAutoIncrement.Connect
此命令将清理剩余的命令。 - 运行新安装程序。
- 添加了打印当前版本或将其保存到文本/CSV文件的选项,现在支持Windows视觉样式,并进行了一些错误修复。
- 版本 3.2
- 支持Visual Studio 2010项目
- 支持Merge module、Cab和Web设置项目
- 在64位系统上正确识别SourceSafe文件夹
- 命令行工具中的
/V
标志会覆盖配置/默认值 - 版本 3.3
- 提供两个安装程序:BuildAutoIncrement.msi用于带永久VCB工具栏/菜单的插件,以及BuildAutoIncrementTemporaryBars.msi用于带临时VCB工具栏/菜单的插件。请查看安装包中的readme.txt文件以获取更多详细信息。
- 解决了每次Visual Studio 2010启动时菜单/工具栏项倍增的问题。
- F#项目将正确显示,包含F#项目的解决方案文件夹也将正确显示所有项目。
- Setup、Merge module、CAB和Web设置项目的版本将正确显示。
- 当Visual Studio的视觉主题被禁用时,GUI也会正常打开。
- 卸载过程中,会显示一个选项对话框,允许用户选择是否自动移除VCB菜单和工具栏。请查看安装包中的readme.txt文件以获取更多详细信息。
- 纠正了Michel Gerber注意到的关于
*
的问题。 非常感谢Thomas Klähn、Stefano Leardini和Pierre Granger帮助我识别了工具栏倍增/消失问题。 - 版本 3.4
- 注意:如果您安装了先前版本,强烈建议先将其卸载。
- 支持Visual Studio 2012和2013(在公开预览版上测试)
- 命令行实用程序支持.vcxproj(Visual Studio 2010引入的C++项目文件格式)
- 支持InstallShield LE
- Visual Studio 2008/2009/2010/2012/2013的插件使用基于XML文件的注册。Visual Studio 2003和2005的插件仍然使用基于COM的注册。
- 版本 3.5
- 修复了菜单索引的问题。
- Addin对TFS的支持已恢复。