1

I am writing a program with a listbox filled with items, and when you right click the item, context menu will pop up and have an option to choose call "Open with", and my question is how to make the "Choose a default program" window to show up, like the image below.

http://postimg.org/image/8ykfrzmjv/

I know you need to do Process.Start() in order to open it, but I do not know the exe name.

Dmitry
  • 13,797
  • 6
  • 32
  • 48
Softmochi
  • 119
  • 1
  • 11

2 Answers2

6

You can use this way to show "Open With" dialog directly:

string FilePath = "C:\\Text.txt";//Your File Path
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.EnableRaisingEvents = false;
proc.StartInfo.FileName = "rundll32.exe";
proc.StartInfo.Arguments = "shell32,OpenAs_RunDLL " + FilePath;
proc.Start();
Angus Chung
  • 1,547
  • 1
  • 11
  • 13
  • This entrypoint is undocumented, doesn't always work as desired, and is subject to change w/o notice. KeithS' OpenWithDialog solution is the right way to do it. – Howard Kapustein Jul 08 '17 at 19:12
4

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.

Community
  • 1
  • 1
KeithS
  • 70,210
  • 21
  • 112
  • 164
  • Is there a way to only set the application and not open it after setting it? I'm trying to just set the application and not actually open the program afterwards. e.g. If i set all .txt files to open with Notepad i don't want it to open notepad with the txt file rather just set it. Is that possible? – Zer0 Jul 04 '15 at 02:46
  • That's probably better accomplished by editing the registry; the selections made in the "Open With" dialog are stored in HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\. Your program would need full trust to do this. – KeithS Jul 16 '15 at 17:03
  • Zer0>Is that possible? Not reliably. The user's default is managed by Windows, how/where is (intentionally) undocumented last I'd heard and its implementation is subject to change w/o notice. If there's no API to set it (and there shouldn't be), then no, you shouldn't be hacking the system to set it directly. Doing so makes you indistinguishable from malware and its less-directly-evil user-experience-where-the-user-isn't-in-control cousins. Applications have abused directly setting the user's defaults hence the reasons Windows takes some steps to safeguard it against direct manipulation. – Howard Kapustein Jul 08 '17 at 19:13