- 标题:
通过文件后缀名获取关联可执行程序 - 标签:
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替换为标准字符串,并在内部根据条件转换或保留原生和宽字符串的形态。
至此,已可通过指定后缀名获取关联程序。