How can I display the "open with" dialog for an unregistered file extension?

I use

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

Edit (inspired by David's comment and https://stackoverflow.com/a/13229516/1431618): One can omit ShellExecute and RunDll32 by calling OpenAs_RunDLL directly:

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;

There is also SHOpenWithDialog on Windows Vista and later. (I find it interesting that Microsoft wrote a RunDLL compatible entry point but until Vista didn't bother to provide a regular API function.)


Simply do not use explicit verb. Using a specific verb like 'open' is a big mistake:

  • 'open' may be not a default verb (for example, it may be 'play', 'edit' or 'run')
  • 'open' may not exists

It is a way more correct to simply pass nil as verb. The system will automatically select most appropriate verb:

  • Default verb will be used, if it is set
  • 'open' verb will be used, if no default verb is set
  • first verb will be used, if no default and 'open' verbs are available
  • if no verbs are assigned - the system will bring "Open with" dialog

In other words, simple

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

will show "Open with" dialog.

Only use a specific verb if you want a specific action. E.g. 'print', 'explore', 'runas'. Otherwise - just pass nil.


Go with following code you will get your solution-

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.