手头有个项目产出物在压缩成ZIP文件的时候,老板要求在文件名中包含版本号。
做为一个懒人就想一次性实现编译,压缩,于是乎呢就写了一个批处理文件。
set PRODUCT_NAME=****
set SOLUTION_PATH=****
# clean solution
"%VS100COMNTOOLS%..\IDE\devenv" "%SOLUTION_PATH%" /clean "Release|Any Cpu"
# build
"%VS100COMNTOOLS%..\IDE\devenv" "%SOLUTION_PATH%" /build "Release|Any Cpu"
# create temporary folder
md temp
cd temp
#copy file
cd ..
.\7-zip\7z a -tzip "%PRODUCT_NAME%.zip" ./temp/* -r -mx=9
#delete temporary folder
rd temp /s/q
这些轻易搞定后就觉得每次都要查看产出物版本不爽,就自己琢磨怎么通过代码得到DLL的版本号呢?对于DLL或者EXE来说版本号存储在资源中,所以应该可以通过打开相应文件查找资源来搞定。具体查找资料的过程不赘述,共享代码各位品读。
#include#include /** * @fn PVOID GetModuleFileVersionPtr( HMODULE hmodule ) * @brief Get the file version from module. * @param hmodule Handle to the module whose executable file contains the resource. * @return If successful, returns a VS_FIXEDFILEINFO pointer, otherwise returns NULL. */ PVOID GetModuleFileVersionPtr( HMODULE hmodule ) { HRSRC hrsrc = 0; HGLOBAL hgrsrc = 0; UINT8 *pres = NULL; VS_FIXEDFILEINFO *pBlock = NULL; int magic = 0x28; int where = 1; /* Find Resource */ hrsrc = FindResource(hmodule, MAKEINTRESOURCE(VS_VERSION_INFO), MAKEINTRESOURCE(RT_VERSION)); if ( 0 != hrsrc ) { ++where; hgrsrc = LoadResource( hmodule, hrsrc ); // no unload needed if ( SizeofResource( hmodule, hrsrc ) < (magic + sizeof(VS_FIXEDFILEINFO)) ) { hrsrc = 0; // size too small? } } if ( 0 != hgrsrc ) { ++where; pres = (UINT8*)LockResource(hgrsrc); // no unlock needed } if ( NULL != pres ) { ++where; pBlock = (VS_FIXEDFILEINFO*)((char*)pres + magic); // Signature must be 0xfeef04bd (see winver.h). if ( 0xfeef04bd != pBlock->dwSignature ) { pBlock = NULL; // smth wrong } } return pBlock; } int main(int argc, char *argv[]) { if(argc == 2) { char *chPath = argv[1]; size_t len = strlen(chPath) + 1; size_t converted = 0; wchar_t *wchPath; /* malloc memory */ wchPath = (wchar_t*)malloc(len*sizeof(wchar_t)); if(wchPath) { /* convert char to wchar_t */ mbstowcs_s(&converted, wchPath, len, chPath, _TRUNCATE); HMODULE hModule = LoadLibraryEx(wchPath, NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE); if(hModule) { /* Get file version */ VS_FIXEDFILEINFO *pBlock = (VS_FIXEDFILEINFO*)GetModuleFileVersionPtr(hModule); if(pBlock) { /* Converted */ WORD whProductMS = HIWORD(pBlock->dwProductVersionMS), wlProductMS = LOWORD(pBlock->dwProductVersionMS), whProductLS = HIWORD(pBlock->dwProductVersionLS), wlProductLS = LOWORD(pBlock->dwProductVersionLS); /* Output to a text file */ FILE *pFile = fopen("currenversion.txt", "w"); if(pFile) { char chVersion[64] = {0}; sprintf(chVersion, "%u.%u.%u.%04u", whProductMS, wlProductMS, whProductLS, wlProductLS); fputs(chVersion, pFile); fclose(pFile); } } /* Frees the loaded dynamic-link library (DLL) module(must be). */ FreeLibrary(hModule); } free(wchPath); } } return 0; }
以上代码未曾精雕细琢,可以写的更精细些,比如可以在参数中指定输出的文本文件名等等。下面可以看看修改后的批处理文件:
set PRODUCT_NAME=****
set SOLUTION_PATH=****
# clean solution
"%VS100COMNTOOLS%..\IDE\devenv" "%SOLUTION_PATH%" /clean "Release|Any Cpu"
# build
"%VS100COMNTOOLS%..\IDE\devenv" "%SOLUTION_PATH%" /build "Release|Any Cpu"
# create temporary folder
md temp
cd temp
#copy file
cd ..
GetVersion.exe "***.dll"
set /p BUILD_NUM=
.\7-zip\7z a -tzip "%PRODUCT_NAME% %BUILD_NUM%.zip" ./temp/* -r -mx=9
#delete temporary folder
rd temp /s/q