Запустите связанную программу или покажите диалог "Открыть с помощью" из другой программы
В седьмом окне следующая команда отображает диалоговое окно, а затем завершается без каких-либо других действий. Почему?
Ожидаемый эффект запуска соответствующей программы Notepad++
или по крайней мере Notepad
RUNDLL32.EXE SHELL32.DLL,OpenAs_RunDLL D:\doc\toto.txt
3 ответа
Решение очень простое: 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
выбран следующий диалог:
и когда выбран переключатель внизу, отображается следующее диалоговое окно:
Это именно то, что я хочу.
Во-первых, обратите внимание, что OpenAs_RunDLL
является недокументированной точкой входа, поэтому единственная причина, по которой он должен работать, состоит в том, что он появляется в реестре HKEY_CLASSES_ROOT как реализация для Open With
глагол оболочки (по крайней мере, в некоторых версиях Windows).
Это только означает, что он может работать при вызове соответствующими функциями оболочки. Это не значит, что он обязательно будет работать в любом произвольном контексте.
На моей домашней машине (Windows Vista) звонит OpenAs_RunDLL
с помощью rundll32
работает (т. е. указанный файл открывается с использованием выбранного приложения), когда команда запускается через диалоговое окно "Пуск" в меню "Пуск", которое можно открыть с помощью сочетания клавиш Windows+R
,
Он не работает, когда выдается из окна консоли командной строки, и симптомы такие же, как вы описали: диалоговое окно отображается, но приложение не запускается. Это совершенно законное поведение, потому что вы используете недокументированную точку входа в контексте, для которого она не предназначена.
Поскольку нет гарантии, что OpenAs_RunDLL
будет существовать вообще в будущих версиях Windows, результат прост: не используйте его. Используйте поддерживаемые SHOpenWithDialog
Функция API вместо этого, или использовать ShellExecute
или же ShellExecuteEx
с openas
глагол; последнее может быть особенно полезным, потому что это легко сделать из скриптового языка, такого как VBScript.
Основываясь на других ответах на аналогичные вопросы и на код из CodeProject: вызов диалогового окна Open With из вашего приложения с использованием C# и PInvoke.net: 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);
}
}
}