軟體需要更新,需要修改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 <Windows.h>#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;}