我在C++项目的资源中有一个版本资源,其中包含版本号,版权和构建详细信息.是否有一种简单的方法可以在运行时访问它以填充我的帮助/关于对话框,因为我目前正在维护此信息的单独const值.理想情况下,该解决方案应适用于Windows/CE移动版和早期版本的Visual C++(6.0以上版本).
这是我原来答案的编辑版本.
bool GetProductAndVersion(CStringA & strProductName, CStringA & strProductVersion) { // get the filename of the executable containing the version resource TCHAR szFilename[MAX_PATH + 1] = {0}; if (GetModuleFileName(NULL, szFilename, MAX_PATH) == 0) { TRACE("GetModuleFileName failed with error %d\n", GetLastError()); return false; } // allocate a block of memory for the version info DWORD dummy; DWORD dwSize = GetFileVersionInfoSize(szFilename, &dummy); if (dwSize == 0) { TRACE("GetFileVersionInfoSize failed with error %d\n", GetLastError()); return false; } std::vectordata(dwSize); // load the version info if (!GetFileVersionInfo(szFilename, NULL, dwSize, &data[0])) { TRACE("GetFileVersionInfo failed with error %d\n", GetLastError()); return false; } // get the name and version strings LPVOID pvProductName = NULL; unsigned int iProductNameLen = 0; LPVOID pvProductVersion = NULL; unsigned int iProductVersionLen = 0; // replace "040904e4" with the language ID of your resources if (!VerQueryValue(&data[0], _T("\\StringFileInfo\\040904e4\\ProductName"), &pvProductName, &iProductNameLen) || !VerQueryValue(&data[0], _T("\\StringFileInfo\\040904e4\\ProductVersion"), &pvProductVersion, &iProductVersionLen)) { TRACE("Can't obtain ProductName and ProductVersion from resources\n"); return false; } strProductName.SetString((LPCSTR)pvProductName, iProductNameLen); strProductVersion.SetString((LPCSTR)pvProductVersion, iProductVersionLen); return true; }
为了获得与马克答案变化无关的语言结果:
// replace "040904e4" with the language ID of your resources !VerQueryValue(&data[0], _T("\\StringFileInfo\\040904e4\\ProductVersion"), &pvProductVersion, &iProductVersionLen)) { TRACE("Can't obtain ProductName and ProductVersion from resources\n"); return false; }
至
UINT uiVerLen = 0; VS_FIXEDFILEINFO* pFixedInfo = 0; // pointer to fixed file info structure // get the fixed file info (language-independent) if(VerQueryValue(&data[0], TEXT("\\"), (void**)&pFixedInfo, (UINT *)&uiVerLen) == 0) { return false; } strProductVersion.Format("%u.%u.%u.%u", HIWORD (pFixedInfo->dwProductVersionMS), LOWORD (pFixedInfo->dwProductVersionMS), HIWORD (pFixedInfo->dwProductVersionLS), LOWORD (pFixedInfo->dwProductVersionLS));
也许会让你开始的事情:
TCHAR moduleName[MAX_PATH+1]; (void)GetModuleFileName(AfxGetInstanceHandle(), moduleName, MAX_PATH); DWORD dummyZero; DWORD versionSize = GetFileVersionInfoSize(moduleName, &dummyZero); if(versionSize == 0) { return NULL; } void* pVersion = malloc(versionSize); if(pVersion == NULL) { return NULL; } if(!GetFileVersionInfo(moduleName, NULL, versionSize, pVersion)) { free(pVersion); return NULL; } UINT length; VS_FIXEDFILEINFO* pFixInfo; VERIFY(VerQueryValue(pVersionInfo, const_cast("\\"), (LPVOID*)&pFixInfo, &length));
这样的事情将为您提供对资源数据的原始访问并让您入门:
HRSRC res = ::FindResource(NULL, MAKEINTRESOURCE(MY_VERSION_ID), RT_VERSION); DWORD size = ::SizeofResource(NULL, res); HGLOBAL mem = ::LoadResource(NULL, res); LPVOID raw_data = ::LockResource(mem); ... ::FreeResource(mem);
谨防!使用FindResource..LockResource不正确。它有时会工作(就像在我的小型演示程序中一样),有时会导致访问冲突(例如:我正在为其制作演示的生产代码)。
VerQueryValue()文档指出,应改为调用GetFileVersionInfoSize和GetFileVersionInfo。雷蒙德·陈(Raymond Chen)解释,请参见http://blogs.msdn.com/oldnewthing/archive/2006/12/26/1365215.aspx