简体   繁体   English

如何使用 WINAPI 和 C++ 提取可执行文件的文件描述?

[英]How to extract file description of executables using WINAPI and C++?

I am trying to extract the file description of executables.我正在尝试提取可执行文件的文件描述。 The file description is the one seen when you right click on a file, choose Properties and it is in the General tab.文件描述是在您右键单击文件时看到的描述,选择“属性”,它位于“常规”选项卡中。

I have tried using the algorithm found here: https://docs.microsoft.com/en-us/windows/desktop/api/winver/nf-winver-verqueryvaluea but for some files the file description returned is empty although I can see it in the Properties window.我尝试使用此处找到的算法: https : //docs.microsoft.com/en-us/windows/desktop/api/winver/nf-winver-verqueryvaluea但对于某些文件,返回的文件描述为空,尽管我可以看到它在“属性”窗口中。 For example, if I create an executable the file description returned will be empty, but in the Properties window its file description is the same as its name.例如,如果我创建一个可执行文件,返回的文件描述将为空,但在“属性”窗口中,其文件描述与其名称相同。 How can I extract the file description for every executable that has one in the General tab and not get empty strings?如何提取每个在“常规”选项卡中有一个可执行文件的文件描述而不是空字符串?

I am using the functions in the following order:我按以下顺序使用这些功能:

GetFileVersionInfoSize获取文件版本信息大小

GetFileVersionInfo获取文件版本信息

VerQueryValue查询值

StringCchPrintfW StringCchPrintfW

VerQueryValue查询值

StringCchCopyNW StringCchCopyNW

Sometimes it fails at VerQueryValue and sometimes it fails at GetFileVersionInfo.有时在 VerQueryValue 处失败,有时在 GetFileVersionInfo 处失败。 I have also noticed that it fails for Microsoft.Photos.exe我还注意到 Microsoft.Photos.exe 失败

If you want to mimic the shells behaviour, use the shell API, specifically its property system .如果您想模仿 shell 行为,请使用 shell API,特别是它的属性 system

Most of the data shown in the properties dialog can be queried using a set of predefined constants, which are defined in "Propkey.h".属性对话框中显示的大部分数据都可以使用一组预定义的常量进行查询,这些常量在“Propkey.h”中定义。 In this case we want the System.FileDescription property .在这种情况下,我们需要System.FileDescription 属性 To query it, we need its PKEY, which is PKEY_FileDescription .要查询它,我们需要它的 PKEY,即PKEY_FileDescription

One of the easiest ways to query a property is the IShellItem2::GetString() method.查询属性的最简单方法之一是IShellItem2::GetString()方法。 The out parameter ppsz returns a pointer to a string, which must be freed using CoTaskMemFree() . out 参数ppsz返回一个指向字符串的指针,必须使用CoTaskMemFree()释放该字符串。 This is not mentioned by the reference, but is the usual way to free memory allocated for you by the shell.参考文献中没有提到这一点,但这是释放 shell 为您分配的内存的常用方法。

To obtain an IShellItem2 interface from a filesystem path, we can use SHCreateItemFromParsingName() .要从文件系统路径获取 IShellItem2 接口,我们可以使用SHCreateItemFromParsingName()

In the following example, I've wrapped up the reusable code in the function GetShellPropStringFromPath() .在下面的示例中,我将可重用代码封装在函数GetShellPropStringFromPath()

Example C++ console application:示例 C++ 控制台应用程序:

#include <Windows.h>
#include <ShlObj.h>    // Shell API
#include <Propkey.h>   // PKEY_* constants
#include <atlbase.h>   // CComPtr, CComHeapPtr
#include <iostream>
#include <io.h>
#include <fcntl.h>
#include <string>
#include <system_error>

// Wrapper for SHCreateItemFromParsingName(), IShellItem2::GetString()
// Throws std::system_error in case of any error.
std::wstring GetShellPropStringFromPath( LPCWSTR pPath, PROPERTYKEY const& key )
{
    // Use CComPtr to automatically release the IShellItem2 interface when the function returns
    // or an exception is thrown.
    CComPtr<IShellItem2> pItem;
    HRESULT hr = SHCreateItemFromParsingName( pPath, nullptr, IID_PPV_ARGS( &pItem ) );
    if( FAILED( hr ) )
        throw std::system_error( hr, std::system_category(), "SHCreateItemFromParsingName() failed" );
    
    // Use CComHeapPtr to automatically release the string allocated by the shell when the function returns
    // or an exception is thrown (calls CoTaskMemFree).
    CComHeapPtr<WCHAR> pValue;
    hr = pItem->GetString( key, &pValue );
    if( FAILED( hr ) )
        throw std::system_error( hr, std::system_category(), "IShellItem2::GetString() failed" );

    // Copy to wstring for convenience
    return std::wstring( pValue );
}

int main()
{
    CoInitialize( nullptr );   // TODO: error handling
    _setmode( _fileno( stdout ), _O_U16TEXT );  // for proper UTF-16 console output

    try
    {
        // Show some properties of Microsoft.Photos.exe (adjust path if necessary)
        LPCWSTR path = LR"(C:\Program Files\WindowsApps\Microsoft.Windows.Photos_2018.18061.17410.0_x64__8wekyb3d8bbwe\Microsoft.Photos.exe)";
        std::wcout << L"PKEY_FileDescription:      " 
                   << GetShellPropStringFromPath( path, PKEY_FileDescription ) << std::endl;
        std::wcout << L"PKEY_Software_ProductName: " 
                   << GetShellPropStringFromPath( path, PKEY_Software_ProductName ) << std::endl;
    }
    catch( std::system_error const& e )
    {
        std::cout << "ERROR: " << e.what() << "\nError code: " << e.code() << std::endl;
    }

    CoUninitialize();
}

Output:输出:

PKEY_FileDescription:      Microsoft.Photos.exe
PKEY_Software_ProductName: Microsoft Photos

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM