软件需要更新,需要修改DLL或者ExE 的版本号,很多时候依赖VS2008 这样的IDE中去修改,然后编译生成。
下面说的方法是通过写代码区修改二进制文件来达到修改版本号的目的。
主要步骤如下:
1. 获取文件头信息大小
2.获取文件头信息内容
3.根据获取的信息内容,通过VerQueryValue函数去获取语言信息
4..根据获取的信息内容,通过VerQueryValue函数获取其他信息,如文件版本信息,产品版本信息等
5.根据获取的版本信息,修改内存内容
6. 通过BeginUpdateResource,UpdateResource,EndUpdateResource 完成资源更新
------------------------------------------------------------------------------
下面是主要代码:
其中CVersion 类是为了将输入的字符串信息分割成4位的数字而已,代码中的version.GetVersion(1) 就是获取版本的第2位.
#include "stdafx.h"
#include
#include "Version.h"
typedef struct _tagLanguage
{
WORD wLanguage;
WORD wCodePage;
} tagLanguage, * LPLanguage;
int _tmain(int argc, _TCHAR* argv[])
{
if (argc!=3)
{
return 0;
}
TCHAR* FileName = argv[1];
TCHAR* Version = argv[2];
//CVersion 类,将字符串“1234,456,789,1110”的版本信息转换成数字,可以自行编写代码
CVersion version(Version);
DWORD dwVerHnd = 0;
//先获取整个文件版本信息的大小
DWORD dwVerInfoSize = GetFileVersionInfoSize(FileName, &dwVerHnd);
//根据大小来申请内存
TCHAR *VerInfo = new TCHAR[dwVerInfoSize];
//获取文件版本信息,这些信息存在刚刚申请的内存中,修改版本信息通过直接修改内存后一次性将版本信息更新
BOOL res = GetFileVersionInfo(FileName,0,dwVerInfoSize,VerInfo);
if (!res)
{
delete []VerInfo;
return 0;
}
//首先在获取的版本信息中读取语言信息,因为修改版本信息需要用到
LPLanguage language = NULL;
UINT size = 0;
VerQueryValue(VerInfo,_T("\\VarFileInfo\\Translation"),(LPVOID*)&language,&size);
//读取文件版本信息
VS_FIXEDFILEINFO* FixedFileInfo=NULL;
VerQueryValue(VerInfo,_T("\\"),(LPVOID*)&FixedFileInfo,&size);
TCHAR TempBuf[MAX_PATH]={0};
if (FixedFileInfo)
{
//修改文件版本信息的版本号,这里通过CVersion 类的分别获取数字“1234”,“456”,“789”,“1110”
//这里需要将高位与低位组合
FixedFileInfo->dwFileVersionMS = MAKELONG(version.GetVersion(1),version.GetVersion(0));
FixedFileInfo->dwFileVersionLS = MAKELONG(version.GetVersion(3),version.GetVersion(2));
FixedFileInfo->dwProductVersionMS = MAKELONG(version.GetVersion(1),version.GetVersion(0));
FixedFileInfo->dwProductVersionMS = MAKELONG(version.GetVersion(3),version.GetVersion(2));
}
//读取StringFileInfo中的信息信息
TCHAR *ProductVer = NULL;
TCHAR *FileVer = NULL;
_stprintf_s(TempBuf,_T("\\StringFileInfo\\%04x%04x\\FileVersion"),language->wLanguage,language->wCodePage);
VerQueryValue(VerInfo,TempBuf,(LPVOID*)&FileVer,&size);
_stprintf_s(TempBuf,_T("\\StringFileInfo\\%04x%04x\\ProductVersion"),language->wLanguage,language->wCodePage);
VerQueryValue(VerInfo,TempBuf,(LPVOID*)&ProductVer,&size);
size_t productlength = _tcslen(ProductVer);
size_t fileLength = _tcslen(FileVer);
if (_tcslen(Version)>productlength)
{
return 0;
}
if (_tcslen(Version)>fileLength)
{
return 0;
}
//修改内存
_tcscpy_s(ProductVer,productlength+1,Version);
_tcscpy_s(FileVer,fileLength+1,Version);
//上面都是读取与修改,这里才是更新资源
HANDLE hResource = BeginUpdateResource(FileName, FALSE);
if (NULL != hResource)
{
//这里参数没错,就是最原始读取的资源,通过修改原有的资源内存,达到更新的目的
res = UpdateResource(hResource, RT_VERSION, MAKEINTRESOURCE(VS_VERSION_INFO), language->wLanguage, VerInfo, dwVerInfoSize);
if (!res)
{
return 0;
}
EndUpdateResource(hResource, FALSE);
}
return 0;
}