34

我在 C++ 项目的资源中有一个版本资源,其中包含版本号、版权和构建详细信息。有没有一种简单的方法可以在运行时访问它以填充我的帮助/关于对话框,因为我目前正在维护此信息的单独 const 值。理想情况下,该解决方案应该适用于 Windows/CE 移动版和早期版本的 Visual C++(6.0 以上)。

4

7 回答 7

35

这是我原始答案的编辑版本。

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;
}
于 2009-07-23T21:48:01.903 回答
16

要获得 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;
}

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));
于 2011-03-07T16:39:23.823 回答
7

类似的东西可能会让你开始,也许:

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));
于 2008-11-25T08:48:49.423 回答
6

像这样的东西会给你对资源数据的原始访问并让你开始:

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);
于 2008-11-25T07:57:48.967 回答
5

谨防!使用 FindResource..LockResource 是不正确的。它有时会起作用(就像在我的小演示程序中所做的那样),有时会导致访问冲突(例如:我正在为其制作演示的生产代码)。

VerQueryValue() 文档指出您应该改为调用 GetFileVersionInfoSize 和 GetFileVersionInfo。Raymond Chen 解释,见http://blogs.msdn.com/oldnewthing/archive/2006/12/26/1365215.aspx

于 2010-02-24T13:02:06.067 回答
0

好的,在 CodeGuru 上进行了更多搜索,发现以下内容。基本上这种方法使用CFileVersionInfo对象来获取任何给定的文件。看看它是否适用于当前运行的 .EXE 文件和 Windows CE 应该很有趣。

于 2008-11-25T08:05:29.263 回答
0

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

于 2012-08-31T16:11:46.137 回答