/// <summary> /// Opens the requested directory in the shell's file/folder browser. /// </summary> /// <param name="parent">The window that is currently in the foreground.</param> /// <param name="folderPath">The folder to open.</param> /// <remarks> /// This UI is presented modelessly, in another process, and in the foreground. /// Error handling and messaging (error dialogs) will be handled by the shell, /// and these errors will not be communicated to the caller of this method. /// </remarks> public static void BrowseFolder(IWin32Window parent, string folderPath) { NativeStructs.SHELLEXECUTEINFO sei = new NativeStructs.SHELLEXECUTEINFO(); sei.cbSize = (uint)Marshal.SizeOf(typeof(NativeStructs.SHELLEXECUTEINFO)); sei.fMask = NativeConstants.SEE_MASK_NO_CONSOLE; sei.lpVerb = "open"; sei.lpFile = folderPath; sei.nShow = NativeConstants.SW_SHOWNORMAL; sei.hwnd = parent.Handle; bool bResult = NativeMethods.ShellExecuteExW(ref sei); if (bResult) { if (sei.hProcess != IntPtr.Zero) { SafeNativeMethods.CloseHandle(sei.hProcess); sei.hProcess = IntPtr.Zero; } } else { NativeMethods.ThrowOnWin32Error("ShellExecuteW returned FALSE"); } GC.KeepAlive(parent); }
private static int ExecShellExecuteEx(IWin32Window parent, string exePath, string args, string verb, out IntPtr hProcess) { string dir; try { dir = Path.GetDirectoryName(exePath); } catch (Exception) { dir = null; } NativeStructs.SHELLEXECUTEINFO sei = new NativeStructs.SHELLEXECUTEINFO(); sei.cbSize = (uint)Marshal.SizeOf(typeof(NativeStructs.SHELLEXECUTEINFO)); sei.fMask = NativeConstants.SEE_MASK_NOCLOSEPROCESS | NativeConstants.SEE_MASK_NO_CONSOLE | NativeConstants.SEE_MASK_FLAG_DDEWAIT; sei.lpVerb = verb; sei.lpDirectory = dir; sei.lpFile = exePath; sei.lpParameters = args; sei.nShow = NativeConstants.SW_SHOWNORMAL; if (parent != null) { sei.hwnd = parent.Handle; } bool bResult = NativeMethods.ShellExecuteExW(ref sei); hProcess = sei.hProcess; sei.hProcess = IntPtr.Zero; int nResult = NativeConstants.ERROR_SUCCESS; if (!bResult) { nResult = Marshal.GetLastWin32Error(); } return(nResult); }
/// <summary> /// Uses the shell to execute the command. This method must only be used by Paint.NET /// and not by plugins. /// </summary> /// <param name="parent"> /// The window that is currently in the foreground. This may be null if requireAdmin /// is false and the executable that exePath refers to is not marked (e.g. via a /// manifest) as requiring administrator privilege. /// </param> /// <param name="exePath"> /// The path to the executable to launch. /// </param> /// <param name="args"> /// The command-line arguments for the executable. /// </param> /// <param name="requireAdmin"> /// Whether or not administrator privilege is required to launch this. However, /// if the executable is already marked as requiring administrator privilege /// (e.g. via a "requiresAdministrator" UAC manifest), this parameter should be /// set to false. /// </param> /// <remarks> /// If administrator privilege is required, a consent UI may be displayed asking the /// user to approve the action. A parent window must be provided in this case so that /// the consent UI will know where to position itself. Administrator privilege is /// required if requireAdmin is set to true, or if the executable being launched /// has a manifest declaring that it requires this privilege and if the operating /// system recognizes the manifest. /// </remarks> /// <exception cref="ArgumentException"> /// requireAdmin was true, but parent was null. /// </exception> /// <exception cref="SecurityException"> /// requireAdmin was true, but the user does not have this privilege, nor do they /// have the ability to acquire or elevate to obtain this privilege. /// </exception> /// <exception cref="Win32Exception"> /// There was an error launching the program. /// </exception> public static void Execute( IWin32Window parent, string exePath, string args, bool requireAdmin, ExecuteWaitType executeWaitType) { const string runAs = "runas"; if (exePath == null) { throw new ArgumentNullException("exePath"); } if (requireAdmin && parent == null) { throw new ArgumentException("If requireAdmin is true, a parent window must be provided"); } // If this action requires admin privilege, but the user does not have this // privilege and is not capable of acquiring this privilege, then we will // throw an exception. if (requireAdmin && !Security.IsAdministrator && !Security.CanElevateToAdministrator) { throw new SecurityException("Executable requires administrator privilege, but user is not an administrator and cannot elevate"); } NativeStructs.SHELLEXECUTEINFO sei = new NativeStructs.SHELLEXECUTEINFO(); sei.cbSize = (uint)Marshal.SizeOf(typeof(NativeStructs.SHELLEXECUTEINFO)); sei.fMask = NativeConstants.SEE_MASK_NOCLOSEPROCESS | NativeConstants.SEE_MASK_NO_CONSOLE | NativeConstants.SEE_MASK_FLAG_DDEWAIT; if (requireAdmin && !Security.IsAdministrator) { sei.lpVerb = runAs; } string dir; try { dir = Path.GetDirectoryName(exePath); } catch (Exception) { dir = null; } sei.lpDirectory = dir; sei.lpFile = exePath; sei.lpParameters = args; sei.nShow = NativeConstants.SW_SHOWNORMAL; if (parent != null) { sei.hwnd = parent.Handle; } string updateMonitorExePath = null; if (executeWaitType == ExecuteWaitType.RelaunchPdnOnExit) { RelaunchPdnHelperPart1(out updateMonitorExePath); } bool bResult = NativeMethods.ShellExecuteExW(ref sei); if (bResult) { if (executeWaitType == ExecuteWaitType.WaitForExit) { SafeNativeMethods.WaitForSingleObject(sei.hProcess, NativeConstants.INFINITE); } else if (executeWaitType == ExecuteWaitType.RelaunchPdnOnExit) { bool bResult2 = SafeNativeMethods.SetHandleInformation( sei.hProcess, NativeConstants.HANDLE_FLAG_INHERIT, NativeConstants.HANDLE_FLAG_INHERIT); RelaunchPdnHelperPart2(updateMonitorExePath, sei.hProcess); // Ensure that we don't close the process handle right away in the next few lines of code. // It must be inherited by the child process. sei.hProcess = IntPtr.Zero; } else if (executeWaitType == ExecuteWaitType.ReturnImmediately) { } if (sei.hProcess != IntPtr.Zero) { SafeNativeMethods.CloseHandle(sei.hProcess); sei.hProcess = IntPtr.Zero; } } else { int dwError = Marshal.GetLastWin32Error(); if (dwError != NativeConstants.ERROR_CANCELLED) { NativeMethods.ThrowOnWin32Error("ShellExecuteW returned FALSE"); } if (updateMonitorExePath != null) { try { File.Delete(updateMonitorExePath); } catch (Exception) { } updateMonitorExePath = null; } } GC.KeepAlive(parent); }
internal static extern bool ShellExecuteExW(ref NativeStructs.SHELLEXECUTEINFO lpExecInfo);