如何从 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 14:35:15  来源:igfitidea点击:

How do I read from a version resource in Visual C++

c++visual-c++resourcesversion

提问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 VerQueryValueAin version.dll. Therefore I use VerQueryValueWinstead of VerQueryValueAeven in projects Multi-byte Character Encoding. Here is my code of ReadVersionfunction

有时我在使用时收到访问冲突VerQueryValueA。但是我在使用时从来没有遇到过这个错误VerQueryValueW。我认为VerQueryValueAversion.dll 有问题。因此,我什至在项目中使用多字节字符编码VerQueryValueW代替VerQueryValueA这是我的ReadVersion功能代码