我想让用户为当前未注册的文件扩展名选择一个关联(打开)。
目前我告诉API使用ShellExecute
打开文件,它会返回ERROR_NO_ASSOCIATION
错误代码。
有没有办法告诉API它应该让用户选择一个新关联?
答案 0 :(得分:11)
我用
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://stackoverflow.com/a/13229516/1431618启发):
可以通过直接调用ShellExecute
来省略RunDll32
和OpenAs_RunDLL
:
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函数。)
答案 1 :(得分:3)
使用以下代码,您将获得解决方案 -
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 this variable set "Verb" from presented system registry.
答案 2 :(得分:3)
只是不要使用显式动词。使用像'open'这样的特定动词是一个很大的错误:
简单地将nil作为动词传递是一种更正确的方法。系统将自动选择最合适的动词:
换句话说,简单
ShellExecute(0, nil, 'C:\MyFile.StrangeExt', ...);
将显示“打开方式”对话框。
如果您需要特定操作,请仅使用特定动词。例如。 'print','explore','runas'。否则 - 只传递nil。