如何在Windows 11中调出含指定应用的“打开方式”对话框?
解决Windows 11下Delphi模拟特殊“打开方式”对话框失败的问题
问题分析
错误代码31对应ERROR_BAD_EXE_FORMAT,核心原因是Windows 11的特殊“打开方式”对话框并非通过传统ShellExecute的openas等动词触发,而是依赖系统关联注册UI组件的新逻辑,直接调用传统动词会因格式不匹配报错。
可行解决方案
方案1:调用系统原生OpenWithDialog函数
Windows提供了专门的OpenWithDialog API(需链接shell32.lib),可直接唤起Windows 11的特殊打开方式对话框,代码示例:
uses Windows, ShellAPI; procedure ShowOpenWithDialog(const FilePath: string); var FilePathW: WideString; begin FilePathW := WideString(FilePath); OpenWithDialog(0, PWideChar(FilePathW)); end;
该函数兼容Windows Vista及以上系统,Windows 11完全适配。
方案2:用ShellExecuteEx配合SEE_MASK_INVOKEIDLIST标志
通过指定openas动词并启用SEE_MASK_INVOKEIDLIST,绕开传统执行路径触发系统关联选择逻辑:
uses Windows, ShellAPI; function ShellExecuteOpenAs(const FilePath: string): Boolean; var sei: TShellExecuteInfo; begin FillChar(sei, SizeOf(sei), 0); sei.cbSize := SizeOf(sei); sei.fMask := SEE_MASK_INVOKEIDLIST; sei.lpVerb := 'openas'; sei.lpFile := PChar(FilePath); sei.nShow := SW_SHOWNORMAL; Result := ShellExecuteEx(@sei); end;
注意:必须传入绝对文件路径,相对路径会导致系统无法定位文件,仍触发错误31。
方案3:通过COM接口IApplicationAssociationRegistrationUI调用
这是更底层的系统接口,精准控制关联选择对话框:
uses Windows, ActiveX, ShlObj; procedure ShowAssociationUI(const FilePath: string); var pRegUI: IApplicationAssociationRegistrationUI; hr: HRESULT; begin CoInitialize(nil); try hr := CoCreateInstance(CLSID_ApplicationAssociationRegistrationUI, nil, CLSCTX_INPROC_SERVER, IID_IApplicationAssociationRegistrationUI, pRegUI); if SUCCEEDED(hr) then begin pRegUI.LaunchAdvancedAssociationUI(0, PWideChar(WideString(FilePath))); end; finally CoUninitialize; end; end;
使用前需初始化COM环境,使用后记得释放资源。
内容的提问来源于stack exchange,提问作者alancc
相关产品推荐
相关产品推荐

