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

泄露秘密 提交于 2019-11-26 11:28:02

问题


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


回答1:


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.




回答2:


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);
        }
    }
}



回答3:


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:

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

That's exactly what I want.



来源:https://stackoverflow.com/questions/23566667/launch-associated-program-or-show-open-with-dialog-from-another-program

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!