C++ 如何使用VerQueryValue获取FileDescription(让示例发挥作用)?

C++ 如何使用VerQueryValue获取FileDescription(让示例发挥作用)?,c++,c,winapi,C++,C,Winapi,我试图通过WinAPI函数VerQueryValue获取文件的各种属性,如“详细信息”选项卡所示。我已成功地使用此函数通过VS_FIXEDFILEINFO获取非字符串版本信息,但未能使函数文档底部显示的信息正常工作 这个例子实际上并不完整,因为它省去了使用其他相关函数和使用函数所需要的一些缓冲区的构造,所以我已经填空了我能做的最好的部分,并在其中的一些步骤之间改变了使用C++ SL,因为这是我最终需要使用的语言: #include <iostream> #include <io

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

这个例子实际上并不完整,因为它省去了使用其他相关函数和使用函数所需要的一些缓冲区的构造,所以我已经填空了我能做的最好的部分,并在其中的一些步骤之间改变了使用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;
}
VerQueryValue(verData,subBlock.c_str(),&lpBuffer,&bufferSize);

std::cout std::cout不知道有关WCHAR[]的bean,请使用std::wcout。确实喜欢调试器。
lpBuffer
null终止吗?@Mayur是的,尽管在调用return之前字符串的长度也放在“puLen”(这里是bufferSize)缓冲区参数中,文档中没有提到,但实际上它是null终止的,至少在我的带有SDK 10.0.18362的Windows 10机器上是这样(证明:)。一般来说,您不应该依赖于一个实现,但对这种行为进行更改无疑会破坏许多应用程序,这一点非常重要,我怀疑它是否会改变。如果您仍然希望安全,在C++中,可以使用构造函数STD::WSCONTRON((const TCHAR *)LpBuffic,*PulEN)指定STR长度,或者在C中,可以分配一个缓冲区,即*PulEN + 1,StrucPLPFug进入它,然后执行缓冲区[*Pule+1 ] =‘0’@ Mayur,而不是最堆栈溢出的正式对象。但我意识到我忘了在我最后的回答中告诉你。现在我明白为什么那个论点是无效的**。我习惯于这些函数让您为“输出”提供指向自己缓冲区的指针,但在本例中,它在内部构造结果并更改您提供的指针,以便最终指向结果的开头,因为它是C样式的字符串。我将更新这个问题,以使用您的更正。@Oblivionth Right,
void**
是一个致命的赠品。另一个自然的问题是谁拥有该指针以及如何处置它。答案是:“包含一个指针的地址,该指针指向pBlock指向的缓冲区中请求的版本信息。当关联的pBlock内存被释放时,LPBUFFER指向的内存被释放。”。因此,返回时,
lpBuffer
实际上指向大
verData
块内部的某个地方。
//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;