获取文件属性“详细信息” - StringFileInfo
参考链接:
1、MS docs - GetFileVersionInfoA:https://docs.microsoft.com/zh-cn/windows/desktop/api/winver/nf-winver-getfileversioninfoa
2、Cppblog - Win32汇编--使用资源—版本信息资源:http://www.cppblog.com/luqingfei/archive/2010/09/21/127239.html
3、CSDN blog - 【PE】Windows资源文件rc定义和使用:https://blog.csdn.net/soaringlee_fighting/article/details/80596261
4、CSDN blog - 获取EXE版本信息 GetFileVersionInfo:https://blog.csdn.net/mfkjq/article/details/53064243
在一些hips软件中,会显示一些exe、dll、sys等的厂商信息,这些信息便存在于"详细信息"中。
0、什么是StringFileInfo
通俗来说,这里的“详细信息”指PE文件(dll,exe,sys等)的信息,包括属性页中的“详细信息”tab页中一部分内容。
对应VS中的.rc
中的VS_VERSION_INFO
信息
以及*.rc
文件源码中的VS_VERSION_INFO
部分
1、获取方法
如果E文可以,请直接阅读MS Docs中GetFileVersionInfoA说明,详细权威,且VerQueryValueA部分有一段示例代码。
微软version.lib(version.dll)
提供了中的3个函数用来获取这些信息,获取步骤:
- 首先使用
GetFileVersionInfoSizeA(W)
获取VersionInfo的大小,申请缓冲区; - 接着使用
GetFileVersionInfoA(W)
获取VersionInfo数据到缓冲区 - 接着使用
VerQueryValueA(W)
依次获取\
,\VarFileInfo\Translation
,再根据Translation获取语言类型,接着\VarFileInfo\080404B0\CompanyName
便获取到了厂商信息。
附:CompanyName域可取值:
2、示例代码
// conGetVer.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include <tchar.h>
#include <windows.h>
#include <iostream>
// pName可取值:
// _T("CompanyName"),_T("FileDescription"),_T("FileVersion"),
// _T("InternalName"),_T("LegalCopyright"),_T("OriginalFilename"),
// _T("ProductName"),_T("ProductVersion"),
BOOL GetFileVersionString(LPCTSTR pFileName, LPCTSTR pName /* = NULL */, LPTSTR ptBuf, UINT lenBuf)
{
DWORD dwDummyHandle = 0; // will always be set to zero
DWORD dwLen = 0;
BYTE* pVersionInfo = NULL;
BOOL bRetVal;
VS_FIXEDFILEINFO FileVersion;
HMODULE hVerDll;
hVerDll = LoadLibrary(_T("VERSION.dll"));
if (hVerDll == NULL)
return FALSE;
#ifdef _UNICODE
typedef DWORD(WINAPI *Fun_GetFileVersionInfoSize)(LPCTSTR, DWORD *);
typedef BOOL(WINAPI *Fun_GetFileVersionInfo)(LPCTSTR, DWORD, DWORD, LPVOID);
typedef BOOL(WINAPI *Fun_VerQueryValue)(LPCVOID, LPCTSTR, LPVOID, PUINT);
#else
typedef DWORD(WINAPI *Fun_GetFileVersionInfoSize)(LPCSTR, DWORD *);
typedef BOOL(WINAPI *Fun_GetFileVersionInfo)(LPCSTR, DWORD, DWORD, LPVOID);
typedef BOOL(WINAPI *Fun_VerQueryValue)(LPCVOID, LPCSTR, LPVOID, PUINT);
#endif
Fun_GetFileVersionInfoSize pGetFileVersionInfoSize;
Fun_GetFileVersionInfo pGetFileVersionInfo;
Fun_VerQueryValue pVerQueryValue;
#ifdef _UNICODE
pGetFileVersionInfoSize = (Fun_GetFileVersionInfoSize)::GetProcAddress(hVerDll, "GetFileVersionInfoSizeW");
pGetFileVersionInfo = (Fun_GetFileVersionInfo)::GetProcAddress(hVerDll, "GetFileVersionInfoW");
pVerQueryValue = (Fun_VerQueryValue)::GetProcAddress(hVerDll, "VerQueryValueW");
#else
pGetFileVersionInfoSize = (Fun_GetFileVersionInfoSize)::GetProcAddress(hVerDll, "GetFileVersionInfoSizeA");
pGetFileVersionInfo = (Fun_GetFileVersionInfo)::GetProcAddress(hVerDll, "GetFileVersionInfoA");
pVerQueryValue = (Fun_VerQueryValue)::GetProcAddress(hVerDll, "VerQueryValueA");
#endif
struct TRANSLATION {
WORD langID; // language ID
WORD charset; // character set (code page)
} Translation;
Translation.langID = 0x0409; //
Translation.charset = 1252; // default = ANSI code page
dwLen = pGetFileVersionInfoSize(pFileName, &dwDummyHandle);
if (dwLen == 0)
{
bRetVal = FALSE;
goto End;
}
pVersionInfo = new BYTE[dwLen]; // allocate version info
bRetVal = pGetFileVersionInfo(pFileName, 0, dwLen, pVersionInfo);
if (bRetVal == FALSE)
{
goto End;
}
VOID * pVI;
UINT uLen;
bRetVal = pVerQueryValue(pVersionInfo, _T("\\"), &pVI, &uLen);
if (bRetVal == FALSE)
{
goto End;
}
memcpy(&FileVersion, pVI, sizeof(VS_FIXEDFILEINFO));
bRetVal = pVerQueryValue(pVersionInfo, _T("\\VarFileInfo\\Translation"),
&pVI, &uLen);
if (bRetVal && uLen >= 4)
{
memcpy(&Translation, pVI, sizeof(TRANSLATION));
}
else
{
bRetVal = FALSE;
goto End;
}
// BREAKIF(FileVersion.dwSignature != VS_FFI_SIGNATURE);
if (FileVersion.dwSignature != VS_FFI_SIGNATURE)
{
bRetVal = FALSE;
goto End;
}
VOID *pVal;
UINT iLenVal;
if (pName == NULL)
{
_stprintf_s(ptBuf, lenBuf, _T("%d.%d.%d.%d"),
HIWORD(FileVersion.dwFileVersionMS), LOWORD(FileVersion.dwFileVersionMS),
HIWORD(FileVersion.dwFileVersionLS), LOWORD(FileVersion.dwFileVersionLS));
}
else
{
TCHAR szQuery[1024];
_stprintf_s(szQuery, 1024, _T("\\StringFileInfo\\%04X%04X\\%s"),
Translation.langID, Translation.charset, pName);
bRetVal = pVerQueryValue(pVersionInfo, szQuery, &pVal, &iLenVal);
if (bRetVal)
{
_stprintf_s(ptBuf, lenBuf, _T("%s"), (TCHAR*)pVal);
}
else
{
_stprintf_s(ptBuf, lenBuf, _T("%s"), _T(""));
}
}
End:
FreeLibrary(hVerDll);
hVerDll = NULL;
delete[] pVersionInfo;
pVersionInfo = NULL;
return bRetVal;
}
int main()
{
TCHAR* ptszStr = NULL;
ptszStr = new TCHAR[1024];
BOOL bRet = GetFileVersionString(_T("F:\\Wireshark-win32-1.11.2.exe"),
_T("CompanyName"), ptszStr, 1024);
delete ptszStr;
ptszStr = NULL;
std::cout << "Hello World!\n";
}