c++ - 如何使用 VerQueryValue 获取 FileDescription(让示例运行)?

标签 c++ c winapi

我正在尝试使用 WinAPI 函数 VerQueryValue 获取文件的各种属性,如其“详细信息”选项卡中所示。我已成功使用此函数通过 VS_FIXEDFILEINFO 获取非字符串版本信息,但无法获取 example显示在功能文档工作的底部。

这个例子实际上并不完整,因为它遗漏了其他相关函数的使用以及使用该函数所需的一些缓冲区的构造,所以我已经尽我所能填补了空白并改变了一些使用 C++ SL 的中间步骤,因为这最终是我需要使用它的语言:

#include <iostream>
#include <iomanip>
#include "sstream"
#include "Windows.h"
#pragma comment(lib, "Version.lib")

int ReadOutFileDescriptions(std::wstring filename)
{
    LPBYTE lpBuffer = NULL;
    DWORD  verHandle, verSize = GetFileVersionInfoSize(filename.c_str(), &verHandle);

    if (verSize != NULL)
    {
        LPSTR verData = new char[verSize];

        if (GetFileVersionInfo(filename.c_str(), verHandle, verSize, verData))
        {
            UINT cbTranslate;

            // Structure used to store enumerated languages and code pages.
            struct LANGANDCODEPAGE {
                WORD wLanguage;
                WORD wCodePage;
            } *lpTranslate;

            // Read the list of languages and code pages.
            VerQueryValue(verData, TEXT("\\VarFileInfo\\Translation"), (LPVOID*)&lpTranslate, &cbTranslate);

            // Read the file description for each language and code page.
            for (ULONGLONG i = 0; i < (cbTranslate / sizeof(struct LANGANDCODEPAGE)); i++)
            {
                std::wostringstream ss; ss << std::setfill(L'0') << std::hex;
                ss << std::setw(4) << lpTranslate[i].wLanguage;
                std::wstring langS = ss.str();
                ss.str(std::wstring());
                ss << std::setw(4) << lpTranslate[i].wCodePage;
                std::wstring codeS = ss.str();
                std::wstring subBlock = L"\\StringFileInfo\\" + langS + codeS + L"\\FileDescription";

                // Retrieve file description for language and code page "i".
                WCHAR descBuffer[50];
                LPVOID lpBuffer = &descBuffer;
                UINT bufferSize;
                VerQueryValue(verData, subBlock.c_str(), &lpBuffer, &bufferSize);
                
                std::cout << bufferSize << '\n' << descBuffer; 
            }
        }

        delete[] verData;
    }

    return 0;
}

int main(int argc, char* argv[])
{
    ReadOutFileDescriptions(L"MyFile.exe");
    return 0;
}

我对 WinAPI 及其类型定义只有一点点经验,而且我的 C 语言有点生疏,所以我确定我只是错误地设置/使用了缓冲区等。

打印的缓冲区大小是正确的(MyFile.exe 的描述长度 + 1 表示空字符)所以我知道函数正在获取正确的值,但实际获取的值打印的只是一系列十六进制字符,很可能是地址。

我做错了什么?

编辑(答案): 感谢@dxiv,我意识到我没有完全理解 VerQueryValue 的“结果”参数(lplpBuffer)是如何在内部和函数返回后使用的。

将循环的结尾更改为以下内容可实现我想要的结果:

//WCHAR descBuffer[50] Not required, the function doesn't utilize a user made buffer
LPVOID lpBuffer;
UINT bufferSize;

VerQueryValue(verData, subBlock.c_str(), &lpBuffer, &bufferSize); // lpBuffer is reassigned here
std::wstring fileDescription((const TCHAR*)lpBuffer); // Create std::string from C style string (char*) that lpBuffer now points to
std::wcout << bufferSize << '\n' << fileDescription;

最佳答案

VerQueryValue(verData, subBlock.c_str(), &lpBuffer, &bufferSize);

std::cout << bufferSize << '\n' << descBuffer; 

一旦 VerQueryValue 返回,lpBuffer 不再指向 descBuffer,而是指向调用内部分配的不同缓冲区。返回的字符串此时位于 (const TCHAR *)lpBuffer

关于c++ - 如何使用 VerQueryValue 获取 FileDescription(让示例运行)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63540335/

相关文章:

c++ - fseek 没有读取所有数据?

c - 如何返回字符指针?

c++ - 编译时计算 (C++ v. C)

windows - 通过Winapi的控制台/GUI代理应用程序

c++ - 使用 C++ 删除 WMI 实例

c++ - 具有等待功能的简单线程

c++ - 模板参数推导针对const指针失败

c++ - 使c++编译器优化以在 map 初始化中调用一次构造函数

c++ - 虚拟析构函数 - 内存泄漏

C使用管道传输数据以使用共享内存写入文件