如何显示未注册文件扩展名的“打开方式”对话框?

10

我希望让用户为当前未注册的文件扩展名选择一个关联应用程序(打开方式)。

目前,我正在使用ShellExecute告诉API打开文件,并返回ERROR_NO_ASSOCIATION错误代码。

有没有一种方法可以告诉API应该让用户选择一个新的关联应用程序?


可能可以这样做:rundll32.exe shell32.dll,OpenAs_RunDLL "C:\Path\TEXT.TXT" - David Heffernan
3个回答

12

我使用

procedure ShellOpenAs(const AFileName: string; AHandle: HWND);
begin
  ShellExecute(AHandle, 'open', PChar('rundll32.exe'), PChar('shell32.dll,OpenAs_RunDLL ' + AFileName), nil, SW_SHOWNORMAL);
end;

编辑(受David评论和https://dev59.com/nGrWa4cB1Zd3GeqP_HOE#13229516的启发): 可以直接调用OpenAs_RunDLL,而不必使用ShellExecuteRunDll32

procedure OpenAs_RunDLL(hwnd: HWND; hinst: HINST; lpszCmdLine: LPSTR; nCmdShow: Integer); stdcall; external shell32;

procedure ShellOpenAs(AHandle: HWND; const AFileName: string);
begin
  OpenAs_RunDLL(AHandle, HInstance, PChar(AFileName), SW_SHOWNORMAL);
end;

在Windows Vista及更高版本中,还存在SHOpenWithDialog。(我认为有趣的是,微软编写了一个与RunDLL兼容的入口点,但直到Vista之前都没有提供常规API函数。)


谢谢,如果第一个失败,我会将其作为备选项添加,因为我只想在无法打开它时才使用对话框。 - Tobias R
1
正确调用对话框的方法是使用 openas 动词:ShellExecute(AHandle, 'openas', PChar(AFileName), nil, nil, SW_SHOWNORMAL); - Remy Lebeau
@Remy:这对我不起作用(Windows 7 64位)。我收到系统错误1155-从德语翻译:“指定的文件没有关联的应用程序”。 - Uli Gerhardt
@UlrichGerhardt:在我的Win7 64位机器上,openas 对于 ShellExecute()ShellExecuteEx() 都有效。 - Remy Lebeau
1
直接调用OpenAs_RunDLL比调用ShellExecute更容易。 - David Heffernan
请注意,OpenAs_RunDLL是未记录的,并且并不总是有效。 - Harry Johnston

4
使用以下代码,您将获得解决方案-
public const uint SEE_MASK_INVOKEIDLIST = 12;//add this line in your code


CoInitializeEx(NULL, COINIT_APARTMENTTHREADED|COINIT_DISABLE_OLE1DDE);
SHELLEXECUTEINFO sei = { sizeof(sei) };
sei.nShow = SW_SHOWNORMAL;
sei.lpVerb = "openas";
sei.lpFile = "C:\\yourfile.ext";
sei.lfmask= SEE_MASK_INVOKEIDLIST;//add this line in your code
ShellExecuteEx(&sei);

SEE_MASK_INVOKEIDLIST是一个变量,从系统注册表中获取“Verb”参数。


这是适用于我的情况(不一定与原帖相同)的正确答案,即在此情况下在Windows 11上显示“选择要打开的应用程序”对话框。 - Dave Nottage

3

不要使用明确的动词。例如,使用特定的动词如“打开”是一个大错误:

  • '打开' 可能不是默认的动词(例如,可能是 '播放','编辑' 或者 '运行')
  • '打开' 可能不存在

更加正确的方法是 将动词设为空。系统会自动选择最合适的动词:

  • 如果设置了默认动词,则使用默认动词
  • 如果没有设置默认动词,则使用 '打开' 动词
  • 如果没有默认动词和 '打开' 动词,则使用第一个动词
  • 如果没有指定动词,则系统会弹出“打开方式”对话框

换句话说,简单明了。

ShellExecute(0, nil, 'C:\MyFile.StrangeExt', ...);

将显示“打开方式”对话框。

只有在需要执行特定操作时才使用特定动词。例如,“打印”,“浏览”,“runas”。否则 - 只需传递nil。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接