通过文件后缀名获取关联可执行程序[AssocQueryString|Shlwapi][associated executable|关联可执行程序][file suffix name|文件后缀名]…

  • 标题:
    通过文件后缀名获取关联可执行程序
  • 标签:
    AssocQueryString | Shlwapi | associated executable | 关联可执行程序 | file suffix name | 文件后缀名 | run program | 启动程序 | open file | 打开文件 | native develop | 原生开发 | Windows develop | Windows开发 | Win32 APP | Win32 API
  • 标注:
    https://www.jianshu.com/p/b9e602ced759
    https://www.jianshu.com/u/1275d25b625e

在尝试打开文件时,我们有时需要预先获取文件的关联程序。这么做可以获取程序的进程信息,以便对变化做出及时的响应。

  • 引入头文件

    本功能属于Windows原生开发,需要引如以下头文件,并根据需要链接静态库。

    #include <windows.h>
    #include <Shlwapi.h>
    #pragma comment (lib,"Shlwapi.lib")
    

  • Qt实现

    由于WindowsAPI的Ex版本会根据构建环境自动切换ANSI和Unicode版本,因此Qt的实现需要在函数内部处理参数。

    #ifdef UNICODE // 适配API的A/W定义.
    #define toStdStringEx toStdWString
    #define fromStdStringEx fromStdWString
    #else
    #define toStdStringEx toStdString
    #define fromStdStringEx fromStdString
    #endif
    

    以下为使用宏的函数实现。函数共查询两次,以保证各类情形的稳定性。

    // 查询与指定后缀名相关联的可执行文件路径.
    // FileSuffixName: 可供系统响应的完整后缀名. 例如`.txt`.
    // -> 关联程序的标准化完整路径. 失败时返回空字串.
    // 参考文章: https://visualstudiomagazine.com/articles/2009/10/13/finding-an-associated-executable.aspx
    // 参考文档: https://learn.microsoft.com/zh-cn/windows/win32/api/shlwapi/nf-shlwapi-assocquerystringa
    QString GetAssociatedExecutablePath(QString FileSuffixName) {
        auto FileSuffixName_StdString = FileSuffixName.toStdStringEx();
        LPCTSTR IN_Suffix = FileSuffixName_StdString.c_str(); // 转换实参.
    
        bool Result_IsValid = false; HRESULT AQS = E_FAIL; // 定义内部判别默认值.
    
        // 此段查询关联程序的DDE名称, 可能得到缺省值OpenWith.
        LPTSTR IO_Result; DWORD* IO_ResultCount; // 重置IO参数.
        IO_Result = new WCHAR[MAX_PATH]; IO_ResultCount  = new DWORD{MAX_PATH}; // 初始化IO参数.
        AssocQueryString(ASSOCF_NONE, ASSOCSTR_DDEAPPLICATION, IN_Suffix, TEXT("open"), IO_Result, IO_ResultCount);
        if (QString::fromStdStringEx(IO_Result) == QString::fromStdStringEx(TEXT("OpenWith"))) goto EXIT;
    
        // 此段查询关联的可执行程序, (经由先前分支所致)不会得到缺省值OpenWith的路径(打开未知文件的系统交互程序).
        delete[] IO_Result; delete IO_ResultCount; // 重置IO参数.
        IO_Result = new WCHAR[MAX_PATH]; IO_ResultCount  = new DWORD{MAX_PATH}; // 初始化IO参数.
        AQS = AssocQueryString(ASSOCF_NONE, ASSOCSTR_EXECUTABLE, IN_Suffix, TEXT("open"), IO_Result, IO_ResultCount);
        if (AQS == S_OK) Result_IsValid = true; goto EXIT;
    
        EXIT: // 函数唯一返回点.
        QString RESULT; if (Result_IsValid) { QFileInfo fi(QString::fromStdStringEx(IO_Result)); RESULT = fi.absoluteFilePath(); }
        delete[] IO_Result; delete IO_ResultCount; // 释放IO参数.
        return RESULT;
    }
    

  • 原生实现

    原项目已在分享本文前决定放弃,因此原生实现未做验证。

    实现已删除。
    请思考自行将QString修改为LPCTSTR,并要求用户使用TEXT宏输入参数;
    或思考将QString替换为标准字符串,并在内部根据条件转换或保留原生和宽字符串的形态。


至此,已可通过指定后缀名获取关联程序。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容