如何从 Visual C++ 中的版本资源读取
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/316626/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I read from a version resource in Visual C++
提问by SmacL
I have a version resource in my resources in a C++ project which contains version number, copyright and build details. Is there an easy way to access this at run-time to populate my help/aboutdialog as I am currently maintaining seperate const values of this information. Ideally, the solution should work for Windows/CE mobile and earlier versions of Visual C++ (6.0 upwards).
我在 C++ 项目的资源中有一个版本资源,其中包含版本号、版权和构建详细信息。是否有一种简单的方法可以在运行时访问它以填充我的帮助/关于对话框,因为我目前正在维护此信息的单独常量值。理想情况下,该解决方案应该适用于 Windows/CE 移动版和早期版本的 Visual C++(6.0 以上)。
回答by Mark Ransom
This is an edited version of my original answer.
这是我原始答案的编辑版本。
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::vector<BYTE> data(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;
}
回答by EdM
To get a language independent result to Mark's answer change :
要获得与 Mark 的答案更改无关的语言结果:
// 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;
}
To
到
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));
回答by Will Dean
Something like might get you started, perhaps:
像这样的东西可能会让你开始,也许:
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<LPTSTR>("\"), (LPVOID*)&pFixInfo, &length));
回答by Rob
Something like this will give you raw access to the resource data and get you started:
像这样的东西会给你原始访问资源数据并让你开始:
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);
回答by Leo
Beware! Using FindResource..LockResource is not correct. It will sometimes work (as it did in my small demo program) and sometimes cause access violations (example: the production code I was making the demo for).
谨防!使用 FindResource..LockResource 是不正确的。它有时会起作用(就像在我的小演示程序中那样),有时会导致访问冲突(例如:我制作演示的生产代码)。
The VerQueryValue() documentation states that you should call GetFileVersionInfoSize and GetFileVersionInfo instead. Raymond Chen explains, see http://blogs.msdn.com/oldnewthing/archive/2006/12/26/1365215.aspx
VerQueryValue() 文档指出您应该改为调用 GetFileVersionInfoSize 和 GetFileVersionInfo。Raymond Chen 解释,参见http://blogs.msdn.com/oldnewthing/archive/2006/12/26/1365215.aspx
回答by SmacL
Ok, a bit more googleing found the followingon CodeGuru. Basically this approach uses the CFileVersionInfoobject to get on any given file. It should be interesting to see if it works on the currently running .EXE file and on Windows CE.
好的,更多的谷歌搜索在 CodeGuru 上找到了以下内容。基本上这种方法使用CFileVersionInfo对象来获取任何给定的文件。看看它是否适用于当前运行的 .EXE 文件和 Windows CE 应该很有趣。
回答by Vitaly
Sometimes I receive Access Violation when use VerQueryValueA
. But I never got this error when use VerQueryValueW
. I think something wrong with VerQueryValueA
in version.dll. Therefore I use VerQueryValueW
instead of VerQueryValueA
even in projects Multi-byte Character Encoding. Here is my code of ReadVersion
function
有时我在使用时收到访问冲突VerQueryValueA
。但是我在使用时从来没有遇到过这个错误VerQueryValueW
。我认为VerQueryValueA
version.dll 有问题。因此,我什至在项目中使用多字节字符编码VerQueryValueW
代替VerQueryValueA
。这是我的ReadVersion
功能代码