自从有了版本控制,Coder 似乎就多了一剂后悔药,让人爽的不行。有时我们会需要在程序中嵌入程序的编译信息,比如,版本修订号、编译日期等,这些对于发行程序和黑盒测试都是很有用的,可以让我们快速定位到数个发行版中的准确版本或者BUG所在。
这里就是介绍如何"自动"同步SVN和程序集的版本信息,Coding 的目的就是让 Coder 更懒。
要完成这个工作,首先要安装 TortoiseSVN及 Subversion,并让你的项目处于 SVN 的版本控制之下。
P.S : 这里推荐 TortoiseSVN 和 AnkhSVN 一起管理项目,TortoiseSVN 做常见任务,AnkhSVN 主要用于在IDE中跟踪状态。
首先,我们需要 SubWCRev.exe,这是由 TortoiseSVN 提供的实用工具,可以获取工作拷贝或版本库的一些信息并通过模板替换。
这里我写了一个类似于函数的 AutoRevision.bat 脚本来直接简化我们的工作。
AutoRevision.bat :
然后创建一个供脚本使用的模板 AssemblyInfo.tpl,内容如下:
AssemblyInfo.tpl
之后为项目添加预生成事件处理命令:
在 属性->项目生成事件->预生成事件命令行 中键入如下代码 :
这里就是介绍如何"自动"同步SVN和程序集的版本信息,Coding 的目的就是让 Coder 更懒。
要完成这个工作,首先要安装 TortoiseSVN及 Subversion,并让你的项目处于 SVN 的版本控制之下。
P.S : 这里推荐 TortoiseSVN 和 AnkhSVN 一起管理项目,TortoiseSVN 做常见任务,AnkhSVN 主要用于在IDE中跟踪状态。
首先,我们需要 SubWCRev.exe,这是由 TortoiseSVN 提供的实用工具,可以获取工作拷贝或版本库的一些信息并通过模板替换。
这里我写了一个类似于函数的 AutoRevision.bat 脚本来直接简化我们的工作。
AutoRevision.bat :
::<code>
:: <revsion>$Rev: 4 $</revision>
:: <owner name="Zealic" mail="rszealic@gmail.com" />
::</code>
::-----------------------------
::<summary>
:: 根据指定的 SVN 工作目录的信息和模板生成目标文件。
::</summary>
::<param name="workDir">要获取信息的 SVN 工作目录。</param>
::<param name="template">模板文件路径。</param>
::<param name="target">生成的目标文件路径。</param>
::<returns>装载量</returns>
::<remark>
:: 当生成项目时 Visual Studio 如果已经打开 %target% 参数指向的文件,那么可能导致模板替换更新不精确。
:: 导致该问题的原因是:SubWCRev.exe 修改了 %target%,但是 VS 检测到了这一情况,会弹出对话框询问用户。
:: 必须重新加载才可以,否则 VS 将会编译未替换过的 %target% 文件。
::</remark>
::=============================
::-----------------------------
::** Initialize
@ECHO OFF
SETLOCAL ENABLEEXTENSIONS
REM Initialize Constants
SET TSVN_INFO_FILE=.\TSVN_INFO.tmp
REM Initialize script arguments
SET workDir=%1
SET template=%2
SET target=%3
REM Goto main entry
GOTO MAIN
::=============================
::-----------------------------
::** Main entry
:MAIN
pushd %workDir%
SET workDir=.\
REM 检查参数
IF %workDir%=="" GOTO ARGUMENT_ERROR
IF %template%=="" GOTO ARGUMENT_ERROR
IF %target%=="" GOTO ARGUMENT_ERROR
REM 查询注册表
reg query HKLM\SOFTWARE\TortoiseSVN /v Directory > %TSVN_INFO_FILE% 2>NUL
REM 查找 TSVN 路径
FOR /F "tokens=*" %%i IN (%TSVN_INFO_FILE%) DO (
ECHO %%i | find "Directory REG_SZ" > NUL
IF %ERRORLEVEL% == 0 (
ECHO %%i > %TSVN_INFO_FILE%
)
)
SET /P TSVN_PATH= < %TSVN_INFO_FILE%
SET TSVN_PATH=%TSVN_PATH:~23,-1%
REM 调用 TSVN 替换模板
IF NOT %ERRORLEVEL% == 0 GOTO UNKNOW_ERROR
"%TSVN_PATH%bin\SubWCRev.exe" %workDir% %template% %target%
IF NOT %ERRORLEVEL% == 0 GOTO UNKNOW_ERROR
GOTO SUCESSED
::=============================
::-----------------------------
::** Error handlers
:ARGUMENT_ERROR
ECHO 传入的参数无效。
GOTO FAIL
:NOT_FOUND_TSVN
ECHO 查询TortoiseSVN 的安装信息失败。
GOTO FAIL
:UNKNOW_ERROR
ECHO 未知错误。
:FAIL
::=============================
::-----------------------------
::** Program exit
:FAIL
DEL /Q %TSVN_INFO_FILE% 2>NUL
ECHO 模板替换失败。
popd
EXIT 1
:SUCESSED
DEL /Q %TSVN_INFO_FILE% 2>NUL
ECHO 成功进行了模板替换。
popd
EXIT 0
::=============================
:: <revsion>$Rev: 4 $</revision>
:: <owner name="Zealic" mail="rszealic@gmail.com" />
::</code>
::-----------------------------
::<summary>
:: 根据指定的 SVN 工作目录的信息和模板生成目标文件。
::</summary>
::<param name="workDir">要获取信息的 SVN 工作目录。</param>
::<param name="template">模板文件路径。</param>
::<param name="target">生成的目标文件路径。</param>
::<returns>装载量</returns>
::<remark>
:: 当生成项目时 Visual Studio 如果已经打开 %target% 参数指向的文件,那么可能导致模板替换更新不精确。
:: 导致该问题的原因是:SubWCRev.exe 修改了 %target%,但是 VS 检测到了这一情况,会弹出对话框询问用户。
:: 必须重新加载才可以,否则 VS 将会编译未替换过的 %target% 文件。
::</remark>
::=============================
::-----------------------------
::** Initialize
@ECHO OFF
SETLOCAL ENABLEEXTENSIONS
REM Initialize Constants
SET TSVN_INFO_FILE=.\TSVN_INFO.tmp
REM Initialize script arguments
SET workDir=%1
SET template=%2
SET target=%3
REM Goto main entry
GOTO MAIN
::=============================
::-----------------------------
::** Main entry
:MAIN
pushd %workDir%
SET workDir=.\
REM 检查参数
IF %workDir%=="" GOTO ARGUMENT_ERROR
IF %template%=="" GOTO ARGUMENT_ERROR
IF %target%=="" GOTO ARGUMENT_ERROR
REM 查询注册表
reg query HKLM\SOFTWARE\TortoiseSVN /v Directory > %TSVN_INFO_FILE% 2>NUL
REM 查找 TSVN 路径
FOR /F "tokens=*" %%i IN (%TSVN_INFO_FILE%) DO (
ECHO %%i | find "Directory REG_SZ" > NUL
IF %ERRORLEVEL% == 0 (
ECHO %%i > %TSVN_INFO_FILE%
)
)
SET /P TSVN_PATH= < %TSVN_INFO_FILE%
SET TSVN_PATH=%TSVN_PATH:~23,-1%
REM 调用 TSVN 替换模板
IF NOT %ERRORLEVEL% == 0 GOTO UNKNOW_ERROR
"%TSVN_PATH%bin\SubWCRev.exe" %workDir% %template% %target%
IF NOT %ERRORLEVEL% == 0 GOTO UNKNOW_ERROR
GOTO SUCESSED
::=============================
::-----------------------------
::** Error handlers
:ARGUMENT_ERROR
ECHO 传入的参数无效。
GOTO FAIL
:NOT_FOUND_TSVN
ECHO 查询TortoiseSVN 的安装信息失败。
GOTO FAIL
:UNKNOW_ERROR
ECHO 未知错误。
:FAIL
::=============================
::-----------------------------
::** Program exit
:FAIL
DEL /Q %TSVN_INFO_FILE% 2>NUL
ECHO 模板替换失败。
popd
EXIT 1
:SUCESSED
DEL /Q %TSVN_INFO_FILE% 2>NUL
ECHO 成功进行了模板替换。
popd
EXIT 0
::=============================
然后创建一个供脚本使用的模板 AssemblyInfo.tpl,内容如下:
AssemblyInfo.tpl
/**
<code>
<revsion>$Rev$ </revision>
<owner name="Zealic" mail="rszealic@gmail.com" />
</code>
**/
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle(ThisAssembly.Title)]
[assembly: AssemblyDescription(ThisAssembly.Information)]
[assembly: AssemblyConfiguration("From Mars.")]
[assembly: AssemblyCompany("Google")]
[assembly: AssemblyCopyright("版权所有 (C) Baidu 2007")]
[assembly: AssemblyDefaultAlias("Live")]
[assembly: AssemblyProduct("RevTest")]
[assembly: AssemblyTrademark("Yahoo!")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("3FBDB8EE-61FB-46ef-8B61-CC28F46C08B9")]
[assembly: AssemblyVersion(ThisAssembly.Version)]
[assembly: AssemblyFileVersion(ThisAssembly.FileVersion)]
internal static class ThisAssembly
{
public const string Title = "RevTest";
public const string Version = "1.2.0." + Revision;
public const string FileVersion = Version;
public const string BuildTime = "$WCNOW$";
public const string Revision = "$WCREV$";
public const string RevisionRange = "$WCRANGE$";
public const string RevisionMixed = "$WCMIXED?True:False$";
public const string RevisionModified = "$WCMODS?True:False$";
public const string Information = "Name=" + Title + "\r\n"
#if DEBUG
+ "Build=DEBUG\r\n"
#elif RELEASE
+ "Build=RELEASE\r\n"
#else
+ "Build=UNKNOW\r\n"
#endif
+ "Revision=" + Revision + "\r\n"
+ "RevRange=" + RevisionRange + "\r\n"
+ "RevMixed=" + RevisionMixed + "\r\n"
+ "Modified=" + RevisionModified + "\r\n\r\n"
+ BuildTime + "\r\n";
}
<code>
<revsion>$Rev$ </revision>
<owner name="Zealic" mail="rszealic@gmail.com" />
</code>
**/
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle(ThisAssembly.Title)]
[assembly: AssemblyDescription(ThisAssembly.Information)]
[assembly: AssemblyConfiguration("From Mars.")]
[assembly: AssemblyCompany("Google")]
[assembly: AssemblyCopyright("版权所有 (C) Baidu 2007")]
[assembly: AssemblyDefaultAlias("Live")]
[assembly: AssemblyProduct("RevTest")]
[assembly: AssemblyTrademark("Yahoo!")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("3FBDB8EE-61FB-46ef-8B61-CC28F46C08B9")]
[assembly: AssemblyVersion(ThisAssembly.Version)]
[assembly: AssemblyFileVersion(ThisAssembly.FileVersion)]
internal static class ThisAssembly
{
public const string Title = "RevTest";
public const string Version = "1.2.0." + Revision;
public const string FileVersion = Version;
public const string BuildTime = "$WCNOW$";
public const string Revision = "$WCREV$";
public const string RevisionRange = "$WCRANGE$";
public const string RevisionMixed = "$WCMIXED?True:False$";
public const string RevisionModified = "$WCMODS?True:False$";
public const string Information = "Name=" + Title + "\r\n"
#if DEBUG
+ "Build=DEBUG\r\n"
#elif RELEASE
+ "Build=RELEASE\r\n"
#else
+ "Build=UNKNOW\r\n"
#endif
+ "Revision=" + Revision + "\r\n"
+ "RevRange=" + RevisionRange + "\r\n"
+ "RevMixed=" + RevisionMixed + "\r\n"
+ "Modified=" + RevisionModified + "\r\n\r\n"
+ BuildTime + "\r\n";
}
之后为项目添加预生成事件处理命令:
在 属性->项目生成事件->预生成事件命令行 中键入如下代码 :
"$(ProjectDir)\Properties\AutoRevision.bat" "$(ProjectDir)" .\Properties\AssemblyInfo.tpl .\Properties\AssemblyInfo.cs
这样,程序就可以在每次编译的时候自动更新程序集信息了,我们可以在 <AssemblyFile>.exe->属性->版本->备注中看到如下信息:
Name=RevTest
Build=DEBUG
Revision=4
RevRange=4
RevMixed=False
Modified=False
2007/12/05 19:00:35
Build=DEBUG
Revision=4
RevRange=4
RevMixed=False
Modified=False
2007/12/05 19:00:35
示例工程下载 : RevTest.rar