获取DLL或者EXE版本号

手头有个项目产出物在压缩成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


你可能感兴趣的:(开发,DLL,C++)