diff --git a/Plugins/Wox.Plugin.CMD/CMD.cs b/Plugins/Wox.Plugin.CMD/CMD.cs index 6cd940396e..eef2564f6a 100644 --- a/Plugins/Wox.Plugin.CMD/CMD.cs +++ b/Plugins/Wox.Plugin.CMD/CMD.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; @@ -64,7 +65,7 @@ namespace Wox.Plugin.CMD IcoPath = "Images/cmd.png", Action = (c) => { - ExecuteCmd(m); + ExecuteCMD(m); return true; } })); @@ -97,7 +98,7 @@ namespace Wox.Plugin.CMD IcoPath = "Images/cmd.png", Action = (c) => { - ExecuteCmd(m.Key); + ExecuteCMD(m.Key); return true; } }; @@ -116,7 +117,7 @@ namespace Wox.Plugin.CMD IcoPath = "Images/cmd.png", Action = (c) => { - ExecuteCmd(cmd); + ExecuteCMD(cmd); return true; } }; @@ -134,21 +135,32 @@ namespace Wox.Plugin.CMD IcoPath = "Images/cmd.png", Action = (c) => { - ExecuteCmd(m.Key); + ExecuteCMD(m.Key); return true; } }).Take(5); return history.ToList(); } - private void ExecuteCmd(string cmd, bool runAsAdministrator = false) + private void ExecuteCMD(string cmd, bool runAsAdministrator = false) { - var fullCmd = CMDStorage.Instance.LeaveCmdOpen ? $"cmd /k \"{cmd}\" & pause & exit" : cmd; - var success = context.API.ShellRun(fullCmd, runAsAdministrator); - if (success) + var arguments = CMDStorage.Instance.LeaveCmdOpen ? $"/k {cmd}" : $"/c {cmd} & pause"; + var info = new ProcessStartInfo { + UseShellExecute = true, + FileName = "cmd.exe", + Arguments = arguments, + Verb = runAsAdministrator ? "runas" : "" + }; + try + { + Process.Start(info); CMDStorage.Instance.AddCmdHistory(cmd); } + catch (FileNotFoundException e) + { + MessageBox.Show($"Command not found: {e.Message}"); + } } public void Init(PluginInitContext context) @@ -215,7 +227,7 @@ namespace Wox.Plugin.CMD Action = c => { context.API.HideApp(); - ExecuteCmd(selectedResult.Title, true); + ExecuteCMD(selectedResult.Title, true); return true; }, IcoPath = "Images/cmd.png" diff --git a/Plugins/Wox.Plugin.Everything/Main.cs b/Plugins/Wox.Plugin.Everything/Main.cs index cd80d35c84..c65ccec8e4 100644 --- a/Plugins/Wox.Plugin.Everything/Main.cs +++ b/Plugins/Wox.Plugin.Everything/Main.cs @@ -5,7 +5,6 @@ using System.IO; using System.Linq; using System.Reflection; using System.ServiceProcess; -using Wox.Infrastructure; using Wox.Plugin.Everything.Everything; namespace Wox.Plugin.Everything @@ -57,7 +56,11 @@ namespace Wox.Plugin.Everything r.Action = (c) => { context.API.HideApp(); - context.API.ShellRun(path); + Process.Start(new ProcessStartInfo + { + FileName = path, + UseShellExecute = true + }); return true; }; r.ContextData = s; @@ -124,12 +127,12 @@ namespace Wox.Plugin.Everything { List defaultContextMenus = new List(); ContextMenu openFolderContextMenu = new ContextMenu() - { - Name = context.API.GetTranslation("wox_plugin_everything_open_containing_folder"), - Command = "explorer.exe", - Argument = " /select,\"{path}\"", - ImagePath = "Images\\folder.png" - }; + { + Name = context.API.GetTranslation("wox_plugin_everything_open_containing_folder"), + Command = "explorer.exe", + Argument = " /select,\"{path}\"", + ImagePath = "Images\\folder.png" + }; defaultContextMenus.Add(openFolderContextMenu); return defaultContextMenus; diff --git a/Plugins/Wox.Plugin.Program/Programs.cs b/Plugins/Wox.Plugin.Program/Programs.cs index 3dd2a3fdbd..b73173a226 100644 --- a/Plugins/Wox.Plugin.Program/Programs.cs +++ b/Plugins/Wox.Plugin.Program/Programs.cs @@ -42,7 +42,7 @@ namespace Wox.Plugin.Program Action = (e) => { context.API.HideApp(); - context.API.ShellRun(c.ExecutePath); + Process.Start(c.ExecutePath); return true; } }).ToList(); @@ -198,7 +198,11 @@ namespace Wox.Plugin.Program Action = _ => { context.API.HideApp(); - context.API.ShellRun(p.ExecutePath, true); + Process.Start( new ProcessStartInfo + { + FileName = p.ExecutePath, + Verb = "runas" + }); return true; }, IcoPath = "Images/cmd.png" @@ -209,19 +213,10 @@ namespace Wox.Plugin.Program Action = _ => { context.API.HideApp(); - String Path = p.ExecutePath; - //check if shortcut - if (Path.EndsWith(".lnk")) - { - //get location of shortcut - var resolved = ShortcutHelper.ResolveShortcut(Path); - if(!string.IsNullOrEmpty(resolved)) - Path = resolved; - } //get parent folder - Path = Directory.GetParent(Path).FullName; + var folderPath = Directory.GetParent(p.ExecutePath).FullName; //open the folder - context.API.ShellRun("explorer.exe " + Path, false); + Process.Start(folderPath); return true; }, IcoPath = "Images/folder.png" diff --git a/Plugins/Wox.Plugin.Program/ShortcutHelper.cs b/Plugins/Wox.Plugin.Program/ShortcutHelper.cs deleted file mode 100644 index def9640ede..0000000000 --- a/Plugins/Wox.Plugin.Program/ShortcutHelper.cs +++ /dev/null @@ -1,74 +0,0 @@ -/* - Shortcut resolver. Avoids using IWshRuntimeLibrary - Proposed by Sam Saffron @ StackOverflow -*/ -using System; -using System.Runtime.InteropServices; -using System.Text; - -namespace Wox.Plugin.Program -{ - public class ShortcutHelper - { - #region Signatures - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] - struct WIN32_FIND_DATAW - { - public uint dwFileAttributes; - public long ftCreationTime; - public long ftLastAccessTime; - public long ftLastWriteTime; - public uint nFileSizeHigh; - public uint nFileSizeLow; - public uint dwReserved0; - public uint dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] - public string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - public string cAlternateFileName; - } - - /// The IShellLink interface allows Shell links to be created, modified, and resolved - [ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214F9-0000-0000-C000-000000000046")] - interface IShellLinkW - { - /// Retrieves the path and file name of a Shell link object - void GetPath([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out WIN32_FIND_DATAW pfd, uint fFlags); - } - - [ComImport, Guid("0000010c-0000-0000-c000-000000000046"), - InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - public interface IPersist { } - - [ComImport, Guid("0000010b-0000-0000-C000-000000000046"), - InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - public interface IPersistFile : IPersist - { - new void GetClassID(out Guid pClassID); - [PreserveSig] - void Load([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName, uint dwMode); - } - - const uint STGM_READ = 0; - const int MAX_PATH = 260; - - // CLSID_ShellLink from ShlGuid.h - [ - ComImport(), - Guid("00021401-0000-0000-C000-000000000046") - ] - public class ShellLink - { - } - #endregion - public static string ResolveShortcut(string filename) - { - ShellLink link = new ShellLink(); - ((IPersistFile)link).Load(filename, STGM_READ); - StringBuilder sb = new StringBuilder(MAX_PATH); - WIN32_FIND_DATAW data = new WIN32_FIND_DATAW(); - ((IShellLinkW)link).GetPath(sb, sb.Capacity, out data, 0); - return sb.ToString(); - } - } -} diff --git a/Plugins/Wox.Plugin.Program/Wox.Plugin.Program.csproj b/Plugins/Wox.Plugin.Program/Wox.Plugin.Program.csproj index 4ec3ee3002..fdaec9a924 100644 --- a/Plugins/Wox.Plugin.Program/Wox.Plugin.Program.csproj +++ b/Plugins/Wox.Plugin.Program/Wox.Plugin.Program.csproj @@ -73,7 +73,6 @@ ProgramSuffixes.xaml - diff --git a/Wox.Infrastructure/WindowsShellRun.cs b/Wox.Infrastructure/WindowsShellRun.cs deleted file mode 100644 index 549815f962..0000000000 --- a/Wox.Infrastructure/WindowsShellRun.cs +++ /dev/null @@ -1,315 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Text; - -namespace Wox.Infrastructure -{ - /* - * http://undoc.airesoft.co.uk/shell32.dll/ShellExecCmdLine.php - * - * IDA pseudocodes: - * * CRunDlg::OKPushed https://gist.github.com/anonymous/bb0581d062ae82169768 - * * ShellExecuteCmdLine https://gist.github.com/anonymous/7efeac7a89498e2667d5 - * * PromptForMedia https://gist.github.com/anonymous/4900265ca20a98da0947 - * - * leaked Windows 2000 source codes: - * * rundlg.cpp https://gist.github.com/anonymous/d97e9490e095a40651b0 - * * exec.c https://gist.github.com/anonymous/594d62eb684cf5ff3052 - */ - - public static class WindowsShellRun - { - - [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)] - static extern string PathGetArgs([In] string pszPath); - - [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)] - static extern void PathRemoveArgs([MarshalAs(UnmanagedType.LPTStr)]StringBuilder lpszPath); - - [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)] - static extern void PathUnquoteSpaces([MarshalAs(UnmanagedType.LPTStr)]StringBuilder lpsz); - - [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)] - static extern int PathGetDriveNumber([In] string lpsz); - - const int SHPPFW_IGNOREFILENAME = 4; - - [DllImport("shell32.dll", CharSet = CharSet.Unicode)] - static extern int SHPathPrepareForWrite(IntPtr hwnd, - [MarshalAs(UnmanagedType.IUnknown)] object punkEnableModless, - string pszPath, uint dwFlags); - - static bool PromptForMedia(String cmd, out int driveId) - { - StringBuilder sb = new StringBuilder(cmd, cmd.Length); - PathRemoveArgs(sb); - PathUnquoteSpaces(sb); - - if ((driveId = PathGetDriveNumber(sb.ToString())) != -1 && - SHPathPrepareForWrite(IntPtr.Zero, 0, sb.ToString(), SHPPFW_IGNOREFILENAME) < 0) - // if replace IntPtr.Zero with a form handle, - // it will show a dialog waiting for media insert - // check it here: https://f.cloud.github.com/assets/158528/2008562/6bb65164-874d-11e3-8f66-c8a4773bd5f2.png - { - return false; - } - return true; - } - - [Flags] - enum ShellExecCmdLineFlags - { - SECL_USEFULLPATHDIR = 0x1, - SECL_NO_UI = 0x2, - SECL_4 = 0x4, - SECL_LOG_USAGE = 0x8, - SECL_USE_IDLIST = 0x10, - SECL__IGNORE_ERROR = 0x20, - SECL_RUNAS = 0x40 - } - - const int URLIS_URL = 0; - const int URLIS_FILEURL = 3; - - [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)] - static extern bool UrlIs(string pszUrl, int UrlIs); - - static void ShellExecCmdLine(IntPtr hInstance, IntPtr hwnd, string command, string startDir, global::System.Diagnostics.ProcessWindowStyle nShow, ShellExecCmdLineFlags dwSeclFlags,bool runAsAdministrator = false,bool leaveCmdOpen = false) - { - string cmd = command; - string args = null; - if (UrlIs(command, URLIS_URL)) - cmd = command; - else - { - if (global::System.Environment.OSVersion.Version.Major >= 6) - EvaluateSystemAndUserCommandLine(cmd, startDir, out cmd, out args, dwSeclFlags); - else - EvaluateUserCommandLine(cmd, startDir, out cmd, out args); - } - - if (!UrlIs(cmd, URLIS_URL) - && ( - (dwSeclFlags & ShellExecCmdLineFlags.SECL_USEFULLPATHDIR) == ShellExecCmdLineFlags.SECL_USEFULLPATHDIR - || startDir == null - || startDir.Length == 0)) - { - string dir = QualifyWorkingDir(cmd); - if (dir != null) - startDir = dir; - } - - if (leaveCmdOpen && File.Exists(cmd)) - { - bool needsCommandLine; - - try - { - - var peHeaderReader = new PeHeaderReader(cmd); - - if (peHeaderReader.Is32BitHeader) - needsCommandLine = peHeaderReader.OptionalHeader32.Subsystem == 3; // IMAGE_SUBSYSTEM_WINDOWS_CUI == 3 - else - needsCommandLine = peHeaderReader.OptionalHeader64.Subsystem == 3; - } - - catch (System.Exception) - { - // Error reading the headers. We will try to run the command the standard way. - needsCommandLine = false; - } - - if (needsCommandLine) - { - string cmdExe; - string dummy; - EvaluateSystemAndUserCommandLine("cmd.exe", startDir, out cmdExe, out dummy, dwSeclFlags); - - // check whether user typed >cmd, because we don't want to create 2 nested shells - if (cmdExe != cmd) - { - args = string.Format("/k {0} {1}", cmd, args); - cmd = cmdExe; - } - } - } - - global::System.Diagnostics.ProcessStartInfo startInfo = new global::System.Diagnostics.ProcessStartInfo(); - startInfo.UseShellExecute = true; - startInfo.Arguments = args; - startInfo.FileName = cmd; - if (runAsAdministrator) startInfo.Verb = "runas"; - startInfo.WindowStyle = global::System.Diagnostics.ProcessWindowStyle.Normal; - startInfo.ErrorDialog = (dwSeclFlags | ShellExecCmdLineFlags.SECL_NO_UI) == 0; - startInfo.ErrorDialogParentHandle = hwnd; - startInfo.WorkingDirectory = startDir; - try - { - global::System.Diagnostics.Process.Start(startInfo); - } - catch (System.Exception e) - { - if (!startInfo.ErrorDialog) - throw e; - } - } - - [DllImport("shell32.dll", CharSet = CharSet.Unicode)] - static extern int SHEvaluateSystemCommandTemplate( - string pszCmdTemplate, - out IntPtr ppszApplication, - out IntPtr ppszCommandLine, - out IntPtr ppszParameters - ); - - [DllImport("shell32.dll", CharSet = CharSet.Unicode)] - static extern void PathQualify( - [MarshalAs(UnmanagedType.LPWStr)] StringBuilder psz - ); - - static string QualifyWorkingDir(string pszPath) - { - // special case to make sure the working dir gets set right: - // 1) no working dir specified - // 2) a drive or a root path, or a relative path specified - // derive the working dir from the qualified path. this is to make - // sure the working dir for setup programs "A:setup" is set right - - if (pszPath.IndexOfAny(new char[] { '\\', ':'}) >= 0) - { - // build working dir based on qualified path - if (Directory.Exists(pszPath)) - return pszPath; - - pszPath = Path.GetDirectoryName(pszPath); - if (pszPath != null) - try - { - return Path.GetFullPath(pszPath); - } - catch - { - return pszPath; - } - } - - return null; - } - - static bool CopyCommand(string pszCommand, string pszDir, out string pszOut) - { - pszOut = pszCommand; - if (pszCommand[0] != '"') - { - if (UrlIs(pszCommand, URLIS_URL)) - { - // urls never have params... - if (UrlIs(pszCommand, URLIS_FILEURL)) - pszOut = new Uri(pszCommand).LocalPath; // PathCreateFromUrl(pszCommand, pszOut, &cchOut, 0); - else - pszOut = pszCommand; - - return false; - } - else - { - try - { - pszOut = Path.GetFullPath(pszCommand); // PathQualifyDef(pszOut, pszDir, 0); - } - catch - { - pszOut = pszCommand; - } - - // TODO: deal with attributes - if (File.Exists(pszOut) || Directory.Exists(pszOut)) // PathFileExistsAndAttributes(pszOut, NULL) - return false; - } - } - pszOut = pszCommand; - return true; - } - - static void EvaluateUserCommandLine(string command, string startDir, out string cmd, out string args) - { - if (CopyCommand(command, startDir, out cmd)) - { - // there might be args in that command - args = PathGetArgs(cmd); - if (args != null) - cmd = cmd.Substring(0, cmd.Length - args.Length).Trim(); - } - else - args = null; - - StringBuilder buffer = new StringBuilder(cmd); - PathUnquoteSpaces(buffer); - cmd = buffer.ToString(); - } - - static void EvaluateSystemAndUserCommandLine(string command, string startDir, out string cmd, out string args, ShellExecCmdLineFlags dwSeclFlags) - { - IntPtr pcmd, pcmdl, parg; - int result = SHEvaluateSystemCommandTemplate(command, out pcmd, out pcmdl, out parg); - if (result < 0) - { - if ((dwSeclFlags & ShellExecCmdLineFlags.SECL__IGNORE_ERROR) == 0) - throwHRESULT(result); - - EvaluateUserCommandLine(command, startDir, out cmd, out args); - } - else - { - cmd = Marshal.PtrToStringUni(pcmd); - args = Marshal.PtrToStringUni(parg); - Marshal.FreeCoTaskMem(pcmd); - Marshal.FreeCoTaskMem(pcmdl); - Marshal.FreeCoTaskMem(parg); - } - } - - static int throwHRESULT(int hresult) - { - throw new global::System.IO.IOException( - new global::System.ComponentModel.Win32Exception(hresult ^ -0x7FF90000).Message, - hresult); - } - - public static void Start(string cmd, bool runAsAdministrator = false) - { - Start(cmd, false, IntPtr.Zero,runAsAdministrator); - } - - public static void Start(string cmd, bool showErrorDialog, IntPtr errorDialogHwnd, bool runAsAdministrator = false) - { - cmd = cmd.Trim(); // PathRemoveBlanks - cmd = Environment.ExpandEnvironmentVariables(cmd); // SHExpandEnvironmentStrings - int driveId = -1; - if (PromptForMedia(cmd, out driveId)) - { - string oldCwd = Environment.CurrentDirectory; - string home = Environment.GetEnvironmentVariable("USERPROFILE"); - if(!string.IsNullOrEmpty(home) && Directory.Exists(home)) Environment.CurrentDirectory = home; - ShellExecCmdLine( - IntPtr.Zero, - errorDialogHwnd, - cmd, - null, // i have no ideas about this field - global::System.Diagnostics.ProcessWindowStyle.Normal, - ShellExecCmdLineFlags.SECL__IGNORE_ERROR | ShellExecCmdLineFlags.SECL_USE_IDLIST | ShellExecCmdLineFlags.SECL_LOG_USAGE | (showErrorDialog ? 0 : ShellExecCmdLineFlags.SECL_NO_UI), - runAsAdministrator - ); - if (!string.IsNullOrEmpty(home) && Directory.Exists(home)) Environment.CurrentDirectory = oldCwd; - } - else - { // Device not ready 0x80070015 - throw new global::System.IO.IOException( - new global::System.ComponentModel.Win32Exception(0x15).Message, - -0x7FF90000 | 0x15); - } - } - } -} diff --git a/Wox.Infrastructure/Wox.Infrastructure.csproj b/Wox.Infrastructure/Wox.Infrastructure.csproj index 070d2992b3..08affe03dd 100644 --- a/Wox.Infrastructure/Wox.Infrastructure.csproj +++ b/Wox.Infrastructure/Wox.Infrastructure.csproj @@ -77,7 +77,6 @@ - diff --git a/Wox.Plugin/IPublicAPI.cs b/Wox.Plugin/IPublicAPI.cs index 1672ec9919..cf2d383fa9 100644 --- a/Wox.Plugin/IPublicAPI.cs +++ b/Wox.Plugin/IPublicAPI.cs @@ -21,15 +21,6 @@ namespace Wox.Plugin /// void ShowContextMenu(PluginMetadata plugin, List results); - /// - /// Execute command - /// a replacement to RUN(win+r) function - /// - /// command that want to execute - /// run as administrator - /// - bool ShellRun(string cmd, bool runAsAdministrator = false); - /// /// Change Wox query /// diff --git a/Wox/MainWindow.xaml.cs b/Wox/MainWindow.xaml.cs index 27dfc8c789..804e9cceac 100644 --- a/Wox/MainWindow.xaml.cs +++ b/Wox/MainWindow.xaml.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; -using System.Drawing; using System.IO; using System.Linq; using System.Net; @@ -904,24 +903,6 @@ namespace Wox pnlResult.Visibility = Visibility.Collapsed; } - public bool ShellRun(string cmd, bool runAsAdministrator = false) - { - try - { - if (string.IsNullOrEmpty(cmd)) - throw new ArgumentNullException(); - - WindowsShellRun.Start(cmd, runAsAdministrator); - return true; - } - catch (Exception ex) - { - string errorMsg = string.Format(InternationalizationManager.Instance.GetTranslation("couldnotStartCmd"), cmd); - ShowMsg(errorMsg, ex.Message, null); - } - return false; - } - private void MainWindow_OnDrop(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop))