Launch associated program or show "Open with" dialog from another program
Asked Answered
L

3

5

Under Window Seven, the following command displays a dialog box then terminates without any other action, why?

The expected effect is launching the associated program Notepad++ or at least Notepad

RUNDLL32.EXE SHELL32.DLL,OpenAs_RunDLL D:\doc\toto.txt

enter image description here

Lakh answered 9/5, 2014 at 14:4 Comment(0)
L
4

The solution is very simple: cmde.exe start

Here is the Java code which embed the command:

private void open( File file ) {
   try {
      final String cmd =
         String.format( "cmd.exe /C start %s", file.getAbsolutePath());
      Runtime.getRuntime().exec( cmd );
   }
   catch( final Throwable t ) {
      t.printStackTrace();
   }
}

When .project is selected the following dialog is shown:

enter image description here

and when the radio button at the bottom is chosen the following dialog is shown:

enter image description here

That's exactly what I want.

Lakh answered 10/5, 2014 at 12:25 Comment(2)
This won't work (i.e., won't display the "open with" dialog) for files that already have an associated application, such as the text file in your original example.Brawner
Yes, you're right. I have updated the question's title which was unclear from the beginning...Lakh
B
8

Firstly, note that OpenAs_RunDLL is an undocumented entry point so the only reason to expect it to work is that it appears in the HKEY_CLASSES_ROOT registry as an implementation for the Open With shell verb (in at least some versions of Windows).

This only means it can be expected to work when called by the appropriate shell functions. It does not mean it will necessarily work in any arbitrary context.

On my home machine (Windows Vista) calling OpenAs_RunDLL via rundll32 works (i.e., the specified file is opened using the selected application) when the command is issued via the Start Menu's Run dialog, which can be opened with the keyboard shortcut Windows+R.

It does not work when issued from a command line console window, and the symptoms are the same as you describe: the dialog is presented, but the application is not launched. This is perfectly legitimate behaviour, because you're using an undocumented entry point in a context it wasn't designed for.

Since there is no guarantee that OpenAs_RunDLL will exist at all in future versions of Windows, the upshot is simple: don't use it. Use the supported SHOpenWithDialog API function instead, or use ShellExecute or ShellExecuteEx with the openas verb; the latter may be particularly useful because it is easy to do from a scripting language such as VBScript.

Brawner answered 10/5, 2014 at 1:35 Comment(3)
According to various other answers elsewhere on Stack Overflow, the "openas" verb won't work if the "open" verb is available. So SHOpenWithDialog may be the only reliable solution.Brawner
Can you give an example of a VBScript to use SHOpenWithDialog, please?Lakh
Can't be done from VBScript, as far as I know. You would have to use a language that supports making calls to the Win32 API (such as C).Brawner
L
4

The solution is very simple: cmde.exe start

Here is the Java code which embed the command:

private void open( File file ) {
   try {
      final String cmd =
         String.format( "cmd.exe /C start %s", file.getAbsolutePath());
      Runtime.getRuntime().exec( cmd );
   }
   catch( final Throwable t ) {
      t.printStackTrace();
   }
}

When .project is selected the following dialog is shown:

enter image description here

and when the radio button at the bottom is chosen the following dialog is shown:

enter image description here

That's exactly what I want.

Lakh answered 10/5, 2014 at 12:25 Comment(2)
This won't work (i.e., won't display the "open with" dialog) for files that already have an associated application, such as the text file in your original example.Brawner
Yes, you're right. I have updated the question's title which was unclear from the beginning...Lakh
T
4

Based on other answers to similar questions and on code from CodeProject: Calling the Open With dialog box from your application, using C# and PInvoke.net: SHOpenWithDialog (shell32) this is the code which works for me

ShellHelper.OpenAs(mainForm.Handle, "path/to/file")

both on Windows XP and on Windows Vista and later. This code uses only documented API (no rundll32)

public class ShellHelper
{
    #region http://www.pinvoke.net/default.aspx/shell32/SHOpenWithDialog.html

    [DllImport("shell32.dll", EntryPoint = "SHOpenWithDialog", CharSet = CharSet.Unicode)]
    private static extern int SHOpenWithDialog(IntPtr hWndParent, ref tagOPENASINFO oOAI);

    // http://msdn.microsoft.com/en-us/library/windows/desktop/bb773363(v=vs.85).aspx 
    private struct tagOPENASINFO
    {
        [MarshalAs(UnmanagedType.LPWStr)]
        public string cszFile;

        [MarshalAs(UnmanagedType.LPWStr)]
        public string cszClass;

        [MarshalAs(UnmanagedType.I4)]
        public tagOPEN_AS_INFO_FLAGS oaifInFlags;
    }

    [Flags]
    private enum tagOPEN_AS_INFO_FLAGS
    {
        OAIF_ALLOW_REGISTRATION = 0x00000001,   // Show "Always" checkbox
        OAIF_REGISTER_EXT = 0x00000002,   // Perform registration when user hits OK
        OAIF_EXEC = 0x00000004,   // Exec file after registering
        OAIF_FORCE_REGISTRATION = 0x00000008,   // Force the checkbox to be registration
        OAIF_HIDE_REGISTRATION = 0x00000020,   // Vista+: Hide the "always use this file" checkbox
        OAIF_URL_PROTOCOL = 0x00000040,   // Vista+: cszFile is actually a URI scheme; show handlers for that scheme
        OAIF_FILE_IS_URI = 0x00000080    // Win8+: The location pointed to by the pcszFile parameter is given as a URI
    }

    private static void DoOpenFileWith(IntPtr hwndParent, string sFilename)
    {
        tagOPENASINFO oOAI = new tagOPENASINFO();
        oOAI.cszFile = sFilename;
        oOAI.cszClass = String.Empty;
        oOAI.oaifInFlags = tagOPEN_AS_INFO_FLAGS.OAIF_ALLOW_REGISTRATION | tagOPEN_AS_INFO_FLAGS.OAIF_EXEC;
        SHOpenWithDialog(hwndParent, ref oOAI);
    }

    #endregion

    #region http://www.codeproject.com/Articles/13103/Calling-the-Open-With-dialog-box-from-your-applica

    [Serializable]
    private struct ShellExecuteInfo
    {
        public int Size;
        public uint Mask;
        public IntPtr hwnd;
        public string Verb;
        public string File;
        public string Parameters;
        public string Directory;
        public uint Show;
        public IntPtr InstApp;
        public IntPtr IDList;
        public string Class;
        public IntPtr hkeyClass;
        public uint HotKey;
        public IntPtr Icon;
        public IntPtr Monitor;
    }

    // Code For OpenWithDialog Box

    [DllImport("shell32.dll", SetLastError = true)]
    extern private static bool ShellExecuteEx(ref ShellExecuteInfo lpExecInfo);

    private const uint SW_NORMAL = 1;

    private static void OpenAsOld(IntPtr hwndParent, string file)
    {
        ShellExecuteInfo sei = new ShellExecuteInfo();
        sei.Size = Marshal.SizeOf(sei);
        sei.Verb = "openas";
        sei.File = file;
        sei.Show = SW_NORMAL;
        sei.hwnd = hwndParent;
        if (!ShellExecuteEx(ref sei))
            throw new System.ComponentModel.Win32Exception();
    }

    #endregion

    public static void OpenAs(IntPtr hWndParent, string file)
    {
        if (System.Environment.OSVersion.Version.Major > 5)
        {
            DoOpenFileWith(hWndParent, file);
        }
        else
        {
            OpenAsOld(hWndParent, file);
        }
    }
}
Taps answered 22/8, 2015 at 8:7 Comment(2)
The ShellExecute does not work for me (win10) unless sei.fMask = SEE_MASK_INVOKEIDLIST is set as suggested here https://mcmap.net/q/213252/-how-can-i-display-the-quot-open-with-quot-dialog-for-an-unregistered-file-extension-duplicateSouthbound
While I found this quite helpful, this is a C# answer to a question tagged as Java. This answer should be migrated to the C# question How can I show the “Open with” file dialog?.Inventor

© 2022 - 2024 — McMap. All rights reserved.