启动相关程序或从另一个程序显示“打开方式”对话框

在Window 7下面,下面的命令显示一个对话框,然后终止,没有任何其他操作,为什么?

预期的效果是启动相关的程序Notepad++或至lessNotepad

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

在这里输入图像说明

首先,请注意OpenAs_RunDLL是一个未记录的入口点,所以期望它的工作的唯一原因是它出现在HKEY_CLASSES_ROOT注册表中作为Open With shell动词(至少在某些版本的Windows中)的实现。

这只是意味着它可以被适当的shell函数调用时工作 这并不意味着它必然会在任何情况下工作。

在我的家用机器上(Windows Vista),通过rundll32作品调用OpenAs_RunDLL (即使用选定的应用程序打开指定的文件),当通过开始菜单的运行对话框发出命令时,可以用键盘快捷键Windows+R打开。

从命令行控制台窗口发出时不起作用,症状与您描述的相同:显示对话框,但应用程序未启动。 这是完全合法的行为,因为您在未设计的上下文中使用未记录的入口点。

由于不能保证在未来版本的Windows中将完全存在OpenAs_RunDLL ,结果很简单:不要使用它。 改为使用支持的SHOpenWithDialog API函数,或者使用openas动词使用ShellExecuteShellExecuteEx ; 后者可能特别有用,因为从VBScript等脚本语言很容易做到 。

解决方法非常简单: cmde.exe start

这是嵌入命令的Java代码:

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

当选择.project ,将显示以下对话框:

在这里输入图像说明

当选择底部的单选按钮时,将显示以下对话框:

在这里输入图像说明

这正是我想要的。

基于对类似问题的其他答案以及来自CodeProject的代码:使用C#和PInvoke.net 从应用程序调用Open With对话框 :SHOpenWithDialog(shell32)这是适用于我的代码

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

在Windows XP和Windows Vista及更高版本上都是如此。 此代码只使用记录的API(不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); } } }