Launch associated program or show “Open with” dialog from another program

后端 未结 3 755
耶瑟儿~
耶瑟儿~ 2020-11-30 10:48

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

The expected effect is launching the associated progra

相关标签:
3条回答
  • 2020-11-30 11:14

    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);
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-30 11:28

    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.

    0 讨论(0)
  • 2020-11-30 11:32

    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.

    0 讨论(0)
提交回复
热议问题