The "Open With..." dialog in the Windows Shell is part of explorer.exe and is not its own program. You used to be able to get to it using the "openas" action verb, but that has been redefined as of Vista to mean "Run as Administrator".
There are still some tricks. Other answers have demonstrated the OpenAs_RunDLL method; however it should be known that this is an undocumented entry point and does not always work, especially on Windows Vista and later. The documented (and thus supported) entry point in the API is another function in shell32.dll called SHOpenWithDialog. Here's P/Invoke-based code that will do the trick:
public static class OpenWithDialog
{
[DllImport("shell32.dll", EntryPoint = "SHOpenWithDialog", CharSet = CharSet.Unicode)]
private static extern int SHOpenWithDialog(IWin32Window parent, ref OpenAsInfo info);
private struct OpenAsInfo
{
[MarshalAs(UnmanagedType.LPWStr)]
public string FileName;
[MarshalAs(UnmanagedType.LPWStr)]
public string FileClass;
[MarshalAs(UnmanagedType.I4)]
public OpenAsFlags OpenAsFlags;
}
[Flags]
public enum OpenAsFlags
{
None = 0x00,
AllowRegistration = 0x01,
RegisterExt = 0x02,
ExecFile = 0x04,
ForceRegistration = 0x08,
HideRegistration = 0x20,
UrlProtocol = 0x40,
FileIsUri = 0x80,
}
public static int Show(string fileName, IWin32Window parent = null, string fileClass = null, OpenAsFlags openAsFlags = OpenAsFlags.ExecFile)
{
var openAsInfo = new OpenAsInfo
{
FileName = fileName,
FileClass = fileClass,
OpenAsFlags = openAsFlags
};
return SHOpenWithDialog(parent, ref openAsInfo);
}
}
On the window that opens, the Browse button will freeze the program if you are running it from a thread that doesn't have a message loop attached; it's also recommended that you pass in a Form instance (or some simple WPF interop magic) as the "parent" argument.
Flags beginning with HideRegistration are Vista+ and the last one (FileIsUri) is Windows 8+; they'll be ignored in previous versions which may cause undesirable behavior. By default, the "openAsFlags" parameter is set to open the file with the selected program, which is one of the reasons the RunDLL solution doesn't always work (this value is part of a second argument to OpenAs_RunDLL that isn't included in the runDLL command line). The return value should be zero or positive; a negative value is an error conforming to the WinAPI HRESULT standard.