diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs index 3f7284db7e7..4d67c5740ff 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs @@ -31,13 +31,13 @@ namespace Microsoft.PowerShell.Commands { #region ProcessBaseCommand /// - /// This class implements the base for process commands + /// This class implements the base for process commands. /// public abstract class ProcessBaseCommand : Cmdlet { #region Parameters /// - /// The various process selection modes + /// The various process selection modes. /// internal enum MatchMode { @@ -133,16 +133,16 @@ internal List MatchingProcesses() // before being stopped. PM confirms that this is fine. _matchingProcesses.Sort(ProcessComparison); return _matchingProcesses; - } // MatchingProcesses + } /// - /// sort function to sort by Name first, then Id + /// Sort function to sort by Name first, then Id. /// /// first Process object /// second Process object /// - /// as String.Compare: returns less than zero if x less than y, - /// greater than 0 if x greater than y, 0 if x == y + /// As String.Compare: returns less than zero if x less than y, + /// greater than 0 if x greater than y, 0 if x == y. /// private static int ProcessComparison(Process x, Process y) { @@ -195,7 +195,7 @@ private void RetrieveMatchingProcessesByProcessName() ErrorCategory.ObjectNotFound); } } - } // MatchingProcessesByProcessName + } /// /// Retrieves the list of all processes matching the Id @@ -232,7 +232,7 @@ private void RetrieveMatchingProcessesById() continue; } } - } // MatchingProcessesById + } /// /// Retrieves the list of all processes matching the InputObject @@ -251,10 +251,10 @@ private void RetrieveProcessesByInput() SafeRefresh(process); AddIdempotent(process); } - } // MatchingProcessesByInput + } /// - /// Retrieve the master list of all processes + /// Retrieve the master list of all processes. /// /// /// @@ -428,12 +428,12 @@ internal static bool TryHasExited(Process process) } #endregion Internal - }//ProcessBaseCommand + } #endregion ProcessBaseCommand #region GetProcessCommand /// - /// This class implements the get-process command + /// This class implements the get-process command. /// [Cmdlet(VerbsCommon.Get, "Process", DefaultParameterSetName = NameParameterSet, HelpUri = "https://go.microsoft.com/fwlink/?LinkID=113324", RemotingCapability = RemotingCapability.SupportedByCommand)] @@ -454,7 +454,7 @@ public sealed class GetProcessCommand : ProcessBaseCommand #region Parameters /// - /// Has the list of process names on which to this command will work + /// Has the list of process names on which to this command will work. /// [Parameter(Position = 0, ParameterSetName = NameParameterSet, ValueFromPipelineByPropertyName = true)] [Parameter(Position = 0, ParameterSetName = NameWithUserNameParameterSet, ValueFromPipelineByPropertyName = true)] @@ -471,7 +471,7 @@ public string[] Name } /// - /// gets/sets an array of process IDs + /// Gets/sets an array of process IDs. /// [Parameter(ParameterSetName = IdParameterSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] [Parameter(ParameterSetName = IdWithUserNameParameterSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] @@ -490,7 +490,7 @@ public int[] Id } /// - /// Input is a stream of [collections of] Process objects + /// Input is a stream of [collections of] Process objects. /// [Parameter(ParameterSetName = InputObjectParameterSet, Mandatory = true, ValueFromPipeline = true)] [Parameter(ParameterSetName = InputObjectWithUserNameParameterSet, Mandatory = true, ValueFromPipeline = true)] @@ -507,7 +507,7 @@ public override Process[] InputObject } /// - /// Include the UserName + /// Include the UserName. /// [Parameter(ParameterSetName = NameWithUserNameParameterSet, Mandatory = true)] [Parameter(ParameterSetName = IdWithUserNameParameterSet, Mandatory = true)] @@ -520,7 +520,7 @@ public SwitchParameter IncludeUserName private bool _includeUserName = false; /// - ///To display the modules of a process + /// To display the modules of a process. /// [Parameter(ParameterSetName = NameParameterSet)] @@ -530,7 +530,7 @@ public SwitchParameter IncludeUserName public SwitchParameter Module { get; set; } /// - ///To display the fileversioninfo of the main module of a process + /// To display the fileversioninfo of the main module of a process. /// [Parameter(ParameterSetName = NameParameterSet)] [Parameter(ParameterSetName = IdParameterSet)] @@ -544,7 +544,7 @@ public SwitchParameter IncludeUserName #region Overrides /// - /// Check the elevation mode if IncludeUserName is specified + /// Check the elevation mode if IncludeUserName is specified. /// protected override void BeginProcessing() { @@ -558,13 +558,12 @@ protected override void BeginProcessing() } /// - /// Write the process objects + /// Write the process objects. /// protected override void ProcessRecord() { foreach (Process process in MatchingProcesses()) { - //if module and fileversion are to be displayed if (Module.IsPresent && FileVersionInfo.IsPresent) { ProcessModule tempmodule = null; @@ -573,7 +572,7 @@ protected override void ProcessRecord() ProcessModuleCollection modules = process.Modules; foreach (ProcessModule pmodule in modules) { - //assigning to tempmodule to rethrow for exceptions on 64 bit machines + // Assigning to tempmodule to rethrow for exceptions on 64 bit machines tempmodule = pmodule; WriteObject(pmodule.FileVersionInfo, true); } @@ -611,7 +610,6 @@ protected override void ProcessRecord() } else if (Module.IsPresent) { - //if only modules are to be displayed try { WriteObject(process.Modules, true); @@ -641,7 +639,6 @@ protected override void ProcessRecord() } else if (FileVersionInfo.IsPresent) { - //if fileversion of each process is to be displayed try { ProcessModule mainModule = PsUtils.GetMainModule(process); @@ -684,20 +681,20 @@ protected override void ProcessRecord() { WriteObject(IncludeUserName.IsPresent ? AddUserNameToProcess(process) : (object)process); } - }//for loop - } // ProcessRecord + } + } #endregion Overrides #region Privates /// - /// New PSTypeName added to the process object + /// New PSTypeName added to the process object. /// private const string TypeNameForProcessWithUserName = "System.Diagnostics.Process#IncludeUserName"; /// - /// Add the 'UserName' NoteProperty to the Process object + /// Add the 'UserName' NoteProperty to the Process object. /// /// /// @@ -716,7 +713,7 @@ private static PSObject AddUserNameToProcess(Process process) } /// - /// Retrieve the UserName through PInvoke + /// Retrieve the UserName through PInvoke. /// /// /// @@ -738,7 +735,7 @@ private static string RetrieveProcessUserName(Process process) int error; if (!Win32Native.OpenProcessToken(process.Handle, TOKEN_QUERY, out processTokenHandler)) { break; } - // Set the default length to be 256, so it will be sufficient for most cases + // Set the default length to be 256, so it will be sufficient for most cases. int tokenInfoLength = 256; tokenUserInfo = Marshal.AllocHGlobal(tokenInfoLength); if (!Win32Native.GetTokenInformation(processTokenHandler, Win32Native.TOKEN_INFORMATION_CLASS.TokenUser, tokenUserInfo, tokenInfoLength, out tokenInfoLength)) @@ -759,7 +756,7 @@ private static string RetrieveProcessUserName(Process process) var tokenUser = Marshal.PtrToStructure(tokenUserInfo); - // Set the default length to be 256, so it will be sufficient for most cases + // Set the default length to be 256, so it will be sufficient for most cases. int userNameLength = 256, domainNameLength = 256; var userNameStr = new StringBuilder(userNameLength); var domainNameStr = new StringBuilder(domainNameLength); @@ -786,19 +783,19 @@ private static string RetrieveProcessUserName(Process process) } catch (NotSupportedException) { - // The Process not started yet, or it's a process from a remote machine + // The Process not started yet, or it's a process from a remote machine. } catch (InvalidOperationException) { - // The Process has exited, Process.Handle will raise this exception + // The Process has exited, Process.Handle will raise this exception. } catch (Win32Exception) { - // We might get an AccessDenied error + // We might get an AccessDenied error. } catch (Exception) { - // I don't expect to get other exceptions, + // I don't expect to get other exceptions. } finally { @@ -818,12 +815,12 @@ private static string RetrieveProcessUserName(Process process) } #endregion Privates - }//GetProcessCommand + } #endregion GetProcessCommand #region WaitProcessCommand /// - /// This class implements the Wait-process command + /// This class implements the Wait-process command. /// [Cmdlet(VerbsLifecycle.Wait, "Process", DefaultParameterSetName = "Name", HelpUri = "https://go.microsoft.com/fwlink/?LinkID=135277")] public sealed class WaitProcessCommand : ProcessBaseCommand @@ -855,7 +852,7 @@ public int[] Id } /// - /// Name of the processes to wait on for termination + /// Name of the processes to wait on for termination. /// [Parameter( ParameterSetName = "Name", @@ -875,7 +872,7 @@ public string[] Name } /// - /// If specified, wait for this number of seconds + /// If specified, wait for this number of seconds. /// [Parameter(Position = 1)] [Alias("TimeoutSec")] @@ -902,7 +899,7 @@ public int Timeout #region IDisposable /// - /// Dispose method of IDisposable interface. + /// Dispose method of IDisposable interface. /// public void Dispose() { @@ -938,12 +935,12 @@ private void myProcess_Exited(object sender, System.EventArgs e) private List _processList = new List(); - //Wait handle which is used by thread to sleep. + // Wait handle which is used by thread to sleep. private ManualResetEvent _waitHandle; private int _numberOfProcessesToWaitFor; /// - /// gets the list of process + /// Gets the list of process. /// protected override void ProcessRecord() { @@ -965,10 +962,10 @@ protected override void ProcessRecord() } _processList.Add(process); } - } // ProcessRecord + } /// - /// Wait for the process to terminate + /// Wait for the process to terminate. /// protected override void EndProcessing() { @@ -1010,7 +1007,6 @@ protected override void EndProcessing() { if (!process.HasExited) { - //write the error string message = StringUtil.Format(ProcessResources.ProcessNotTerminated, new object[] { process.ProcessName, process.Id }); ErrorRecord errorRecord = new ErrorRecord(new TimeoutException(message), "ProcessNotTerminated", ErrorCategory.CloseError, process); WriteError(errorRecord); @@ -1024,7 +1020,7 @@ protected override void EndProcessing() } /// - /// StopProcessing + /// StopProcessing. /// protected override void StopProcessing() { @@ -1035,12 +1031,12 @@ protected override void StopProcessing() } #endregion Overrides - }//WaitProcessCommand + } #endregion WaitProcessCommand #region StopProcessCommand /// - /// This class implements the stop-process command + /// This class implements the stop-process command. /// /// /// Processes will be sorted before being stopped. PM confirms @@ -1054,7 +1050,7 @@ public sealed class StopProcessCommand : ProcessBaseCommand { #region Parameters /// - /// Has the list of process names on which to this command will work + /// Has the list of process names on which to this command will work. /// [Parameter( ParameterSetName = "Name", @@ -1075,7 +1071,7 @@ public string[] Name } /// - /// gets/sets an array of process IDs + /// Gets/sets an array of process IDs. /// [Parameter( Position = 0, @@ -1096,7 +1092,7 @@ public int[] Id } /// - /// gets/sets an array of objects + /// Gets/sets an array of objects. /// [Parameter( Position = 0, @@ -1127,8 +1123,6 @@ public SwitchParameter PassThru set { _passThru = value; } } - //Addition by v-ramch Mar 18 2008 - //Added force parameter /// /// Specifies whether to force a process to kill /// even if it has dependent services. @@ -1187,7 +1181,6 @@ protected override void ProcessRecord() } catch (Win32Exception ex) { - // This process could not be stopped, so write a non-terminating error. WriteNonTerminatingError( process, ex, ProcessResources.CouldNotStopProcess, "CouldNotStopProcess", ErrorCategory.CloseError); @@ -1196,7 +1189,6 @@ protected override void ProcessRecord() try { - //check if the process is current process and kill it at last if (Process.GetCurrentProcess().Id == SafeGetProcessId(process)) { _shouldKillCurrentProcess = true; @@ -1205,7 +1197,6 @@ protected override void ProcessRecord() if (Platform.IsWindows && !Force) { - // Check if the process is owned by current user if (!IsProcessOwnedByCurrentUser(process)) { string message = StringUtil.Format( @@ -1219,13 +1210,12 @@ protected override void ProcessRecord() } } - //if the process is svchost stop all the dependent services before killing process + // If the process is svchost stop all the dependent services before killing process if (string.Equals(SafeGetProcessName(process), "SVCHOST", StringComparison.CurrentCultureIgnoreCase)) { StopDependentService(process); } - // kill the process if (!process.HasExited) { process.Kill(); @@ -1235,8 +1225,6 @@ protected override void ProcessRecord() { if (!TryHasExited(process)) { - // This process could not be stopped, - // so write a non-terminating error. WriteNonTerminatingError( process, exception, ProcessResources.CouldNotStopProcess, "CouldNotStopProcess", ErrorCategory.CloseError); @@ -1247,8 +1235,6 @@ protected override void ProcessRecord() { if (!TryHasExited(process)) { - // This process could not be stopped, - // so write a non-terminating error. WriteNonTerminatingError( process, exception, ProcessResources.CouldNotStopProcess, "CouldNotStopProcess", ErrorCategory.CloseError); @@ -1259,7 +1245,7 @@ protected override void ProcessRecord() if (PassThru) WriteObject(process); } - } // ProcessRecord + } /// /// Kill the current process here. @@ -1270,28 +1256,28 @@ protected override void EndProcessing() { StopProcess(Process.GetCurrentProcess()); } - }//EndProcessing + } #endregion Overrides #region Private /// - /// should the current powershell process to be killed + /// Should the current powershell process to be killed. /// private bool _shouldKillCurrentProcess; /// - /// Boolean variables to display the warning using shouldcontinue + /// Boolean variables to display the warning using ShouldContinue. /// private bool _yesToAll,_noToAll; /// - /// Current windows user name + /// Current windows user name. /// private string _currentUserName; /// - /// gets the owner of the process + /// Gets the owner of the process. /// /// /// returns the owner @@ -1319,13 +1305,13 @@ private bool IsProcessOwnedByCurrentUser(Process process) } catch (IdentityNotMappedException) { - //Catching IdentityMappedException - //Need not throw error. + // Catching IdentityMappedException + // Need not throw error. } catch (ArgumentException) { - //Catching ArgumentException. In Win2k3 Token is zero - //Need not throw error. + // Catching ArgumentException. In Win2k3 Token is zero + // Need not throw error. } finally { @@ -1336,7 +1322,7 @@ private bool IsProcessOwnedByCurrentUser(Process process) } /// - /// Stop the service that depends on the process and its child services + /// Stop the service that depends on the process and its child services. /// /// private void StopDependentService(Process process) @@ -1354,7 +1340,6 @@ private void StopDependentService(Process process) string serviceName = oService.CimInstanceProperties["Name"].Value.ToString(); using (var service = new System.ServiceProcess.ServiceController(serviceName)) { - //try stopping the service, if cant we are not writing exception try { service.Stop(); @@ -1376,7 +1361,7 @@ private void StopDependentService(Process process) } /// - /// stops the given process throws non terminating error if cant + /// Stops the given process throws non terminating error if can't. /// process to be stopped /// true if process stopped successfully else false /// @@ -1413,12 +1398,12 @@ private void StopProcess(Process process) } #endregion Private - }//StopProcessCommand + } #endregion StopProcessCommand #region DebugProcessCommand /// - /// This class implements the Debug-process command + /// This class implements the Debug-process command. /// [Cmdlet(VerbsDiagnostic.Debug, "Process", DefaultParameterSetName = "Name", SupportsShouldProcess = true, HelpUri = "https://go.microsoft.com/fwlink/?LinkID=135206")] public sealed class DebugProcessCommand : ProcessBaseCommand @@ -1450,7 +1435,7 @@ public int[] Id } /// - /// Name of the processes to wait on for termination + /// Name of the processes to wait on for termination. /// [Parameter( ParameterSetName = "Name", @@ -1474,11 +1459,10 @@ public string[] Name #region Overrides /// - /// gets the list of process and attach the debugger to the processes + /// Gets the list of process and attach the debugger to the processes. /// protected override void ProcessRecord() { - //for the processes foreach (Process process in MatchingProcesses()) { string targetMessage = StringUtil.Format( @@ -1488,7 +1472,7 @@ protected override void ProcessRecord() if (!ShouldProcess(targetMessage)) { continue; } - // sometimes Idle process has processid zero,so handle that because we cannot attach debugger to it. + // Sometimes Idle process has processid zero,so handle that because we cannot attach debugger to it. if (process.Id == 0) { WriteNonTerminatingError( @@ -1521,12 +1505,12 @@ protected override void ProcessRecord() AttachDebuggerToProcess(process); } - } // ProcessRecord + } #endregion Overrides /// - /// Attach debugger to the process + /// Attach debugger to the process. /// private void AttachDebuggerToProcess(Process process) { @@ -1565,7 +1549,7 @@ private void AttachDebuggerToProcess(Process process) } /// - /// Map the return code from 'AttachDebugger' to error message + /// Map the return code from 'AttachDebugger' to error message. /// private string MapReturnCodeToErrorMessage(int returnCode) { @@ -1587,7 +1571,7 @@ private string MapReturnCodeToErrorMessage(int returnCode) #region StartProcessCommand /// - /// This class implements the Start-process command + /// This class implements the Start-process command. /// [Cmdlet(VerbsLifecycle.Start, "Process", DefaultParameterSetName = "Default", SupportsShouldProcess = true, HelpUri = "https://go.microsoft.com/fwlink/?LinkID=135261")] [OutputType(typeof(Process))] @@ -1599,7 +1583,7 @@ public sealed class StartProcessCommand : PSCmdlet, IDisposable #region Parameters /// - /// Path/FileName of the process to start + /// Path/FileName of the process to start. /// [Parameter(Mandatory = true, Position = 0)] [ValidateNotNullOrEmpty] @@ -1607,7 +1591,7 @@ public sealed class StartProcessCommand : PSCmdlet, IDisposable public string FilePath { get; set; } /// - /// Arguments for the process + /// Arguments for the process. /// [Parameter(Position = 1)] [Alias("Args")] @@ -1615,7 +1599,7 @@ public sealed class StartProcessCommand : PSCmdlet, IDisposable public string[] ArgumentList { get; set; } /// - /// Credentials for the process + /// Credentials for the process. /// [Parameter(ParameterSetName = "Default")] [Alias("RunAs")] @@ -1633,14 +1617,14 @@ public PSCredential Credential private PSCredential _credential; /// - /// working directory of the process + /// Working directory of the process. /// [Parameter] [ValidateNotNullOrEmpty] public string WorkingDirectory { get; set; } /// - /// load user profile from registry + /// Load user profile from registry. /// [Parameter(ParameterSetName = "Default")] [Alias("Lup")] @@ -1656,7 +1640,7 @@ public SwitchParameter LoadUserProfile private SwitchParameter _loaduserprofile = SwitchParameter.Present; /// - /// starts process in a new window + /// Starts process in a new window. /// [Parameter(ParameterSetName = "Default")] [Alias("nnw")] @@ -1672,13 +1656,13 @@ public SwitchParameter NoNewWindow private SwitchParameter _nonewwindow; /// - /// passthru parameter + /// PassThru parameter. /// [Parameter] public SwitchParameter PassThru { get; set; } /// - /// Redirect error + /// Redirect error. /// [Parameter(ParameterSetName = "Default")] [Alias("RSE")] @@ -1695,7 +1679,7 @@ public string RedirectStandardError private string _redirectstandarderror; /// - /// Redirect input + /// Redirect input. /// [Parameter(ParameterSetName = "Default")] [Alias("RSI")] @@ -1712,7 +1696,7 @@ public string RedirectStandardInput private string _redirectstandardinput; /// - /// Redirect output + /// Redirect output. /// [Parameter(ParameterSetName = "Default")] [Alias("RSO")] @@ -1729,18 +1713,17 @@ public string RedirectStandardOutput private string _redirectstandardoutput; /// - /// Verb + /// Verb. /// /// - /// The 'Verb' parameter is not supported in OneCore PowerShell - /// because 'UseShellExecute' is not supported in CoreCLR. + /// The 'Verb' parameter is only supported on Windows Desktop. /// [Parameter(ParameterSetName = "UseShellExecute")] [ValidateNotNullOrEmpty] public string Verb { get; set; } /// - /// Window style of the process window + /// Window style of the process window. /// [Parameter] [ValidateNotNullOrEmpty] @@ -1757,13 +1740,13 @@ public ProcessWindowStyle WindowStyle private bool _windowstyleSpecified = false; /// - /// wait for th eprocess to terminate + /// Wait for the process to terminate. /// [Parameter] public SwitchParameter Wait { get; set; } /// - /// Default Environment + /// Default Environment. /// [Parameter(ParameterSetName = "Default")] public SwitchParameter UseNewEnvironment @@ -1782,7 +1765,7 @@ public SwitchParameter UseNewEnvironment #region overrides /// - /// BeginProcessing + /// BeginProcessing. /// protected override void BeginProcessing() { @@ -1818,12 +1801,11 @@ protected override void BeginProcessing() } } - //create an instance of the ProcessStartInfo Class ProcessStartInfo startInfo = new ProcessStartInfo(); - //use ShellExecute by default if we are running on full windows SKUs + // Use ShellExecute by default if we are running on full windows SKUs startInfo.UseShellExecute = Platform.IsWindowsDesktop; - //Path = Mandatory parameter -> Will not be empty. + // Path = Mandatory parameter -> Will not be empty. try { CommandInfo cmdinfo = CommandDiscovery.LookupCommandInfo( @@ -1835,8 +1817,15 @@ protected override void BeginProcessing() catch (CommandNotFoundException) { startInfo.FileName = FilePath; +#if UNIX + // Arguments are passed incorrectly to the executable used for ShellExecute and not to filename https://github.com/dotnet/corefx/issues/30718 + // so don't use ShellExecute if arguments are specified + + // Linux relies on `xdg-open` and macOS relies on `open` which behave differently than Windows ShellExecute when running console commands + // as a new console will be opened. So to avoid that, we only use ShellExecute on non-Windows if the filename is not an actual command (like a URI) + startInfo.UseShellExecute = (ArgumentList == null); +#endif } - //Arguments if (ArgumentList != null) { StringBuilder sb = new StringBuilder(); @@ -1848,10 +1837,9 @@ protected override void BeginProcessing() startInfo.Arguments = sb.ToString(); ; } - //WorkingDirectory if (WorkingDirectory != null) { - //WorkingDirectory -> Not Exist -> Throw Error + // WorkingDirectory -> Not Exist -> Throw Error WorkingDirectory = ResolveFilePath(WorkingDirectory); if (!Directory.Exists(WorkingDirectory)) { @@ -1864,7 +1852,7 @@ protected override void BeginProcessing() } else { - //Working Directory not specified -> Assign Current Path. + // Working Directory not specified -> Assign Current Path. startInfo.WorkingDirectory = ResolveFilePath(this.SessionState.Path.CurrentFileSystemLocation.Path); } @@ -1875,7 +1863,6 @@ protected override void BeginProcessing() startInfo.UseShellExecute = false; } - //UseNewEnvironment if (_UseNewEnvironment) { startInfo.EnvironmentVariables.Clear(); @@ -1883,21 +1870,17 @@ protected override void BeginProcessing() LoadEnvironmentVariable(startInfo, Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User)); } - //WindowStyle startInfo.WindowStyle = _windowstyle; - //NewWindow if (_nonewwindow) { startInfo.CreateNoWindow = _nonewwindow; } #if !UNIX - //LoadUserProfile. startInfo.LoadUserProfile = _loaduserprofile; #endif if (_credential != null) { - //Gets NetworkCredentials NetworkCredential nwcredential = _credential.GetNetworkCredential(); startInfo.UserName = nwcredential.UserName; if (String.IsNullOrEmpty(nwcredential.Domain)) @@ -1911,7 +1894,7 @@ protected override void BeginProcessing() startInfo.Password = _credential.Password; } - //RedirectionInput File Check -> Not Exist -> Throw Error + // RedirectionInput File Check -> Not Exist -> Throw Error if (_redirectstandardinput != null) { _redirectstandardinput = ResolveFilePath(_redirectstandardinput); @@ -1924,7 +1907,7 @@ protected override void BeginProcessing() } } - //RedirectionInput == RedirectionOutput -> Throw Error + // RedirectionInput == RedirectionOutput -> Throw Error if (_redirectstandardinput != null && _redirectstandardoutput != null) { _redirectstandardinput = ResolveFilePath(_redirectstandardinput); @@ -1938,7 +1921,7 @@ protected override void BeginProcessing() } } - //RedirectionInput == RedirectionError -> Throw Error + // RedirectionInput == RedirectionError -> Throw Error if (_redirectstandardinput != null && _redirectstandarderror != null) { _redirectstandardinput = ResolveFilePath(_redirectstandardinput); @@ -1952,7 +1935,7 @@ protected override void BeginProcessing() } } - //RedirectionOutput == RedirectionError -> Throw Error + // RedirectionOutput == RedirectionError -> Throw Error if (_redirectstandardoutput != null && _redirectstandarderror != null) { _redirectstandarderror = ResolveFilePath(_redirectstandarderror); @@ -1968,19 +1951,15 @@ protected override void BeginProcessing() } else if (ParameterSetName.Equals("UseShellExecute")) { - //Verb if (Verb != null) { startInfo.Verb = Verb; } - //WindowStyle startInfo.WindowStyle = _windowstyle; } string targetMessage = StringUtil.Format(ProcessResources.StartProcessTarget, startInfo.FileName, startInfo.Arguments.Trim()); if (!ShouldProcess(targetMessage)) { return; } - //Starts the Process Process process = Start(startInfo); - //Wait and Passthru Implementation. if (PassThru.IsPresent) { if (process != null) @@ -2047,7 +2026,7 @@ protected override void StopProcessing() #region IDisposable Overrides /// - /// Dispose WaitHandle used to honor -Wait parameter + /// Dispose WaitHandle used to honor -Wait parameter. /// public void Dispose() { @@ -2107,24 +2086,6 @@ private void LoadEnvironmentVariable(ProcessStartInfo startinfo, IDictionary Env private Process Start(ProcessStartInfo startInfo) { -#if UNIX - Process process = new Process() { StartInfo = startInfo }; - SetupInputOutputRedirection(process); - process.Start(); - if (process.StartInfo.RedirectStandardOutput) - { - process.BeginOutputReadLine(); - } - if (process.StartInfo.RedirectStandardError) - { - process.BeginErrorReadLine(); - } - if (process.StartInfo.RedirectStandardInput) - { - WriteToStandardInput(process); - } - return process; -#else Process process = null; if (startInfo.UseShellExecute) { @@ -2132,10 +2093,27 @@ private Process Start(ProcessStartInfo startInfo) } else { +#if UNIX + process = new Process() { StartInfo = startInfo }; + SetupInputOutputRedirection(process); + process.Start(); + if (process.StartInfo.RedirectStandardOutput) + { + process.BeginOutputReadLine(); + } + if (process.StartInfo.RedirectStandardError) + { + process.BeginErrorReadLine(); + } + if (process.StartInfo.RedirectStandardInput) + { + WriteToStandardInput(process); + } +#else process = StartWithCreateProcess(startInfo); +#endif } return process; -#endif } #if UNIX @@ -2324,12 +2302,12 @@ private Process StartWithCreateProcess(ProcessStartInfo startinfo) GCHandle pinnedEnvironmentBlock = new GCHandle(); string message = String.Empty; - //building the cmdline with the file name given and it's arguments + // building the cmdline with the file name given and it's arguments StringBuilder cmdLine = BuildCommandLine(startinfo.FileName, startinfo.Arguments); try { - //RedirectionStandardInput + // RedirectionStandardInput if (_redirectstandardinput != null) { startinfo.RedirectStandardInput = true; @@ -2340,7 +2318,7 @@ private Process StartWithCreateProcess(ProcessStartInfo startinfo) { lpStartupInfo.hStdInput = new SafeFileHandle(ProcessNativeMethods.GetStdHandle(-10), false); } - //RedirectionStandardOutput + // RedirectionStandardOutput if (_redirectstandardoutput != null) { startinfo.RedirectStandardOutput = true; @@ -2351,7 +2329,7 @@ private Process StartWithCreateProcess(ProcessStartInfo startinfo) { lpStartupInfo.hStdOutput = new SafeFileHandle(ProcessNativeMethods.GetStdHandle(-11), false); } - //RedirectionStandardError + // RedirectionStandardError if (_redirectstandarderror != null) { startinfo.RedirectStandardError = true; @@ -2362,40 +2340,40 @@ private Process StartWithCreateProcess(ProcessStartInfo startinfo) { lpStartupInfo.hStdError = new SafeFileHandle(ProcessNativeMethods.GetStdHandle(-12), false); } - //STARTF_USESTDHANDLES + // STARTF_USESTDHANDLES lpStartupInfo.dwFlags = 0x100; int creationFlags = 0; if (startinfo.CreateNoWindow) { - //No new window: Inherit the parent process's console window + // No new window: Inherit the parent process's console window creationFlags = 0x00000000; } else { - //CREATE_NEW_CONSOLE + // CREATE_NEW_CONSOLE creationFlags |= 0x00000010; - //STARTF_USESHOWWINDOW + // STARTF_USESHOWWINDOW lpStartupInfo.dwFlags |= 0x00000001; // On headless SKUs like NanoServer and IoT, window style can only be the default value 'Normal'. switch (startinfo.WindowStyle) { case ProcessWindowStyle.Normal: - //SW_SHOWNORMAL + // SW_SHOWNORMAL lpStartupInfo.wShowWindow = 1; break; case ProcessWindowStyle.Minimized: - //SW_SHOWMINIMIZED + // SW_SHOWMINIMIZED lpStartupInfo.wShowWindow = 2; break; case ProcessWindowStyle.Maximized: - //SW_SHOWMAXIMIZED + // SW_SHOWMAXIMIZED lpStartupInfo.wShowWindow = 3; break; case ProcessWindowStyle.Hidden: - //SW_HIDE + // SW_HIDE lpStartupInfo.wShowWindow = 0; break; } @@ -2465,7 +2443,7 @@ private Process StartWithCreateProcess(ProcessStartInfo startinfo) Marshal.ZeroFreeCoTaskMemUnicode(password); } } - }//end of if + } ProcessNativeMethods.SECURITY_ATTRIBUTES lpProcessAttributes = new ProcessNativeMethods.SECURITY_ATTRIBUTES(); ProcessNativeMethods.SECURITY_ATTRIBUTES lpThreadAttributes = new ProcessNativeMethods.SECURITY_ATTRIBUTES(); @@ -2499,6 +2477,7 @@ private Process StartWithCreateProcess(ProcessStartInfo startinfo) lpProcessInformation.Dispose(); } } +#endif /// /// This method will be used only on Windows full desktop. @@ -2518,7 +2497,6 @@ private Process StartWithShellExecute(ProcessStartInfo startInfo) } return result; } -#endif #endregion } @@ -2637,7 +2615,6 @@ internal static class ProcessNativeMethods internal static UInt32 OPEN_EXISTING = 3; // Methods - // static NativeMethods(); [DllImport(PinvokeDllNames.GetStdHandleDllName, CharSet = CharSet.Ansi, SetLastError = true)] public static extern IntPtr GetStdHandle(int whichHandle); @@ -2805,7 +2782,7 @@ public PROCESS_INFORMATION() } /// - /// Dispose + /// Dispose. /// public void Dispose() { @@ -2813,7 +2790,7 @@ public void Dispose() } /// - /// Dispose + /// Dispose. /// /// private void Dispose(bool disposing) @@ -2855,14 +2832,14 @@ protected override bool ReleaseHandle() #region ProcessCommandException /// - /// Non-terminating errors occurring in the process noun commands + /// Non-terminating errors occurring in the process noun commands. /// [Serializable] public class ProcessCommandException : SystemException { #region ctors /// - /// unimplemented standard constructor + /// Unimplemented standard constructor. /// /// doesn't return public ProcessCommandException() : base() @@ -2871,7 +2848,7 @@ public ProcessCommandException() : base() } /// - /// standard constructor + /// Standard constructor. /// /// /// constructed object @@ -2880,7 +2857,7 @@ public ProcessCommandException(string message) : base(message) } /// - /// standard constructor + /// Standard constructor. /// /// /// @@ -2892,7 +2869,7 @@ public ProcessCommandException(string message, Exception innerException) #region Serialization /// - /// serialization constructor + /// Serialization constructor. /// /// /// @@ -2927,7 +2904,7 @@ public override void GetObjectData( #region Properties /// - /// Name of the process which could not be found or operated upon + /// Name of the process which could not be found or operated upon. /// /// public string ProcessName @@ -2937,8 +2914,8 @@ public string ProcessName } private string _processName = String.Empty; #endregion Properties - } // class ProcessCommandException + } #endregion ProcessCommandException -}//Microsoft.PowerShell.Commands +} diff --git a/src/System.Management.Automation/engine/NativeCommandProcessor.cs b/src/System.Management.Automation/engine/NativeCommandProcessor.cs index 3556ce00316..f0cc2ee348f 100644 --- a/src/System.Management.Automation/engine/NativeCommandProcessor.cs +++ b/src/System.Management.Automation/engine/NativeCommandProcessor.cs @@ -452,16 +452,6 @@ private void InitNativeProcess() throw new PipelineStoppedException(); } - if (!Platform.IsWindows && startInfo.UseShellExecute) - { - // UseShellExecute is not properly supported on Unix. It runs the file with '/bin/sh'. - // Before the behavior is improved (tracked by dotnet/corefx#19956), we use xdg-open/open as the default programs - string executable = Platform.IsLinux ? "xdg-open" : /* macOS */ "open"; - startInfo.Arguments = "\"" + startInfo.FileName + "\" " + startInfo.Arguments; - startInfo.FileName = executable; - startInfo.UseShellExecute = false; - } - try { _nativeProcess = new Process() { StartInfo = startInfo }; diff --git a/src/System.Management.Automation/help/HelpCommands.cs b/src/System.Management.Automation/help/HelpCommands.cs index 580a51ca38f..1ddfe090604 100644 --- a/src/System.Management.Automation/help/HelpCommands.cs +++ b/src/System.Management.Automation/help/HelpCommands.cs @@ -599,11 +599,7 @@ private void LaunchOnlineHelp(Uri uriToLaunch) { this.WriteVerbose(string.Format(CultureInfo.InvariantCulture, HelpDisplayStrings.OnlineHelpUri, uriToLaunch.OriginalString)); System.Diagnostics.Process browserProcess = new System.Diagnostics.Process(); -#if UNIX - browserProcess.StartInfo.FileName = Platform.IsLinux ? "xdg-open" : /* macOS */ "open"; - browserProcess.StartInfo.Arguments = uriToLaunch.OriginalString; - browserProcess.Start(); -#else + if (Platform.IsNanoServer || Platform.IsIoT) { // We cannot open the URL in browser on headless SKUs. @@ -612,12 +608,10 @@ private void LaunchOnlineHelp(Uri uriToLaunch) } else { - // We can call ShellExecute directly on Full Windows. browserProcess.StartInfo.FileName = uriToLaunch.OriginalString; browserProcess.StartInfo.UseShellExecute = true; browserProcess.Start(); } -#endif } catch (InvalidOperationException ioe) { diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index fd860cafd6d..67223acff16 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -1307,11 +1307,11 @@ protected override void InvokeDefaultAction(string path) var invokeProcess = new System.Diagnostics.Process(); invokeProcess.StartInfo.FileName = path; #if UNIX - bool invokeDefaultProgram = false; + bool useShellExecute = false; if (Directory.Exists(path)) { // Path points to a directory. We have to use xdg-open/open on Linux/macOS. - invokeDefaultProgram = true; + useShellExecute = true; } else { @@ -1324,19 +1324,13 @@ protected override void InvokeDefaultAction(string path) { // Error code 13 -- Permission denied // The file is possibly not an executable. We try xdg-open/open on Linux/macOS. - invokeDefaultProgram = true; + useShellExecute = true; } } - if (invokeDefaultProgram) + if (useShellExecute) { - const string quoteFormat = "\"{0}\""; - invokeProcess.StartInfo.FileName = Platform.IsLinux ? "xdg-open" : /* macOS */ "open"; - if (NativeCommandParameterBinder.NeedQuotes(path)) - { - path = string.Format(CultureInfo.InvariantCulture, quoteFormat, path); - } - invokeProcess.StartInfo.Arguments = path; + invokeProcess.StartInfo.UseShellExecute = true; invokeProcess.Start(); } #else