一个偶然的机会,在MSDN看到一种用脚本自动增加版本号的方法:
How To Increment Version Information After Each Build in Visual C++
http://support.microsoft.com/default.aspx?scid=kb;en-us;237870
也许是对VB脚本不是很熟练,几近修改,用的还是不爽;尤其是手下那么多project,挨个改rc应用实在是比较费事。于是,用VC6写了一个插件(DevStudio Add-in)……
我的目的比较简单:
1. 在我没有修改rc文件,把VERSIONINFO挪到其他文件的时候(见上面连接 How to...),这个插件可以直接pass;
2. 我希望build成功之后,如果没有修改过源代码,用不着增加版本号;
3. 如果需要修改版本号,在下次build之前;避免build后修改,由于影响.rc,下次需要重新build。
步骤如下:
1. 首先当然要创建一个project,可以用类型为DevStudio Add-in Wizard的向导。向导完成后,Add-in的框架已经出来了(汗,MS!),要做的事情已经很少了。
2. 修改模板生成的CComands类
2.1 增加一个BOOL型变量m_bUpdateVersion标记是不是有源代码文件被修改过
protected:
BOOL m_bUpdateVersion;
public:
BOOL GetUpdateVersion()
{ return m_bUpdateVersion; };
void SetUpdateVersion(BOOL bUpdateNext)
{ m_bUpdateVersion = bUpdateNext; };
2.2 增加更新版本号的代码
BOOL CCommands::UpdateVersionNO(LPCTSTR lpszVersionFileName)
{
BOOL rt = FALSE;
CComBSTR bstrProjName;
CComPtr<IDispatch> pDisp;
GetApplicationObject()->get_ActiveProject(&pDisp);
CComQIPtr<IGenericProject> pProj = pDisp;
if (pProj)
{
pProj->get_FullName(&bstrProjName);
CString strProjName = (bstrProjName);
CString strPathName, strFileName;
if( GetPathFromFileName(strProjName, strPathName) )
{
strFileName = strPathName + lpszVersionFileName;
CStdioFile versionFile;
try
{
if( versionFile.Open(strFileName, CStdioFile::modeReadWrite) )
{
versionFile.SeekToBegin();
CString strVerFile, strVerProd;
LONG lVerFile[4] = {0, 0, 0, 0};
LONG lVerProd[4] = {0, 0, 0, 0};
CHAR szBufferVerFile[256] = {0};
CHAR szBufferVerProd[256] = {0};
versionFile.ReadString(strVerFile);
versionFile.ReadString(strVerProd);
_stscanf(strVerFile, "#define%s%d,%d,%d,%d", szBufferVerFile, lVerFile+0, lVerFile+1, lVerFile+2, lVerFile+3);
_stscanf(strVerProd, "#define%s%d,%d,%d,%d", szBufferVerProd, lVerProd+0, lVerProd+1, lVerProd+2, lVerProd+3);
if( lstrlen(szBufferVerFile)>0 && lstrlen(szBufferVerProd)>0 )
{
versionFile.SeekToBegin();
versionFile.SetLength(0);
lVerFile[3] ++;
lVerProd[3] ++;
CString strLine;
strLine.Format(_T("#define %s\t\t%d,%d,%d,%d\n"), szBufferVerFile, lVerFile[0], lVerFile[1], lVerFile[2], lVerFile[3]);
versionFile.WriteString(strLine);
strLine.Format(_T("#define %s\t\t%d,%d,%d,%d\n"), szBufferVerProd, lVerProd[0], lVerProd[1], lVerProd[2], lVerProd[3]);
versionFile.WriteString(strLine);
strLine.Format(_T("#define %s_STR\t\"%d, %d, %d, %d\\0\"\n"), szBufferVerFile, lVerFile[0], lVerFile[1], lVerFile[2], lVerFile[3]);
versionFile.WriteString(strLine);
strLine.Format(_T("#define %s_STR\t\"%d, %d, %d, %d\\0\"\n"), szBufferVerProd, lVerProd[0], lVerProd[1], lVerProd[2], lVerProd[3]);
versionFile.WriteString(strLine);
versionFile.WriteString("\n");
}
versionFile.Close();
rt = TRUE;
}
}
catch ( ... )
{
}
}
}
return rt;
}
2.3 在适当的位置判断状态,更新版本号文件:
HRESULT CCommands::XApplicationEvents::DocumentSave(IDispatch* theDocument)
{ //当有源代码更新并保存的时候
....
if( !m_pCommands->GetUpdateVersion() )
{
m_pCommands->SetUpdateVersion(TRUE);
m_pCommands->UpdateVersionNO("Version_NO.h");
}
....
}
HRESULT CCommands::XApplicationEvents::BuildFinish(long nNumErrors, long nNumWarnings)
{ //如果编译成功,有必要重置标志信息,以便下次修改文件的时候同时更新版本号所在文件
...
if( nNumErrors==0 && m_pCommands->GetUpdateVersion() )
{
m_pCommands->SetUpdateVersion(FALSE);
}
...
}
3. 修改工程的Settings,输出位置为\Microsoft Visual Studio\Common\MSDev98\AddIns\****.dll。如果需要调试的话,需要修改release设置的若干项,具体参考release模式下dll的调试。
4. 在其他的project,把.rc的VERSIONINFO转移到.rc2,把FILEVERSION、PRODUCTVERSION等用宏代替,并在一个新文件Version_NO.h中定义这些宏,比如:
#define VERSION_FILE 1,1,0,208
#define VERSION_PROD 1,1,0,208
#define VERSION_FILE_STR "1, 1, 0, 208\0"
#define VERSION_PROD_STR "1, 1, 0, 208\0"