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