diff --git a/src/System.Management.Automation/engine/remoting/commands/EnterPSHostProcessCommand.cs b/src/System.Management.Automation/engine/remoting/commands/EnterPSHostProcessCommand.cs index 756250eb8d7..c3ad65b0506 100644 --- a/src/System.Management.Automation/engine/remoting/commands/EnterPSHostProcessCommand.cs +++ b/src/System.Management.Automation/engine/remoting/commands/EnterPSHostProcessCommand.cs @@ -318,22 +318,19 @@ private static void PrepareRunspace(Runspace runspace) private Process GetProcessById(int procId) { - try - { - return Process.GetProcessById(procId); - } - catch (System.ArgumentException) + var process = PSHostProcessUtils.GetProcessById(procId); + if (process is null) { ThrowTerminatingError( - new ErrorRecord( - new PSArgumentException(StringUtil.Format(RemotingErrorIdStrings.EnterPSHostProcessNoProcessFoundWithId, procId)), - "EnterPSHostProcessNoProcessFoundWithId", - ErrorCategory.InvalidArgument, - this) - ); - - return null; + new ErrorRecord( + new PSArgumentException(StringUtil.Format(RemotingErrorIdStrings.EnterPSHostProcessNoProcessFoundWithId, procId)), + "EnterPSHostProcessNoProcessFoundWithId", + ErrorCategory.InvalidArgument, + this) + ); } + + return process; } private Process GetProcessByHostProcessInfo(PSHostProcessInfo hostProcessInfo) @@ -403,7 +400,7 @@ private void VerifyProcess(Process process) { ThrowTerminatingError( new ErrorRecord( - new PSInvalidOperationException(StringUtil.Format(RemotingErrorIdStrings.EnterPSHostProcessNoPowerShell, Process.ProcessName)), + new PSInvalidOperationException(StringUtil.Format(RemotingErrorIdStrings.EnterPSHostProcessNoPowerShell, Process.Id)), "EnterPSHostProcessNoPowerShell", ErrorCategory.InvalidOperation, this) @@ -599,9 +596,22 @@ private static int[] GetProcIdsFromNames(string[] names) WildcardPattern namePattern = WildcardPattern.Get(name, WildcardOptions.IgnoreCase); foreach (var proc in processes) { - if (namePattern.IsMatch(proc.ProcessName)) + // Skip processes that have already terminated. + if (proc.HasExited) + { + continue; + } + + try { - returnIds.Add(proc.Id); + if (namePattern.IsMatch(proc.ProcessName)) + { + returnIds.Add(proc.Id); + } + } + catch (InvalidOperationException) + { + // Ignore if process has exited in the mean time. } } } @@ -681,10 +691,9 @@ internal static IReadOnlyCollection GetAppDomainNamesFromProc string pName = namedPipe.Substring(pNameIndex + 1); Process process = null; - try { - process = System.Diagnostics.Process.GetProcessById(id); + process = PSHostProcessUtils.GetProcessById(id); } catch (Exception) { @@ -704,10 +713,20 @@ internal static IReadOnlyCollection GetAppDomainNamesFromProc // best effort to cleanup } } - else if (process.ProcessName.Equals(pName, StringComparison.Ordinal)) + else { - // only add if the process name matches - procAppDomainInfo.Add(new PSHostProcessInfo(pName, id, appDomainName, namedPipe)); + try + { + if (process.ProcessName.Equals(pName, StringComparison.Ordinal)) + { + // only add if the process name matches + procAppDomainInfo.Add(new PSHostProcessInfo(pName, id, appDomainName, namedPipe)); + } + } + catch (InvalidOperationException) + { + // Ignore if process has exited in the mean time. + } } } } @@ -796,8 +815,8 @@ internal PSHostProcessInfo( MainWindowTitle = string.Empty; try { - var proc = Process.GetProcessById(processId); - MainWindowTitle = proc.MainWindowTitle ?? string.Empty; + var process = PSHostProcessUtils.GetProcessById(processId); + MainWindowTitle = process?.MainWindowTitle ?? string.Empty; } catch (ArgumentException) { @@ -831,4 +850,30 @@ public string GetPipeNameFilePath() } #endregion + + #region PSHostProcessUtils + + internal static class PSHostProcessUtils + { + /// + /// Return a System.Diagnostics.Process object by process Id, + /// or null if not found or process has exited. + /// + /// Process of Id to find. + /// Process object or null. + public static Process GetProcessById(int procId) + { + try + { + var process = Process.GetProcessById(procId); + return process.HasExited ? null : process; + } + catch (System.ArgumentException) + { + return null; + } + } + } + + #endregion } diff --git a/src/System.Management.Automation/resources/RemotingErrorIdStrings.resx b/src/System.Management.Automation/resources/RemotingErrorIdStrings.resx index 680e6d1a6b5..6cbcdc72ddb 100644 --- a/src/System.Management.Automation/resources/RemotingErrorIdStrings.resx +++ b/src/System.Management.Automation/resources/RemotingErrorIdStrings.resx @@ -1408,7 +1408,7 @@ All WinRM sessions connected to PowerShell session configurations, such as Micro Multiple processes were found with this name {0}. Use the process Id to specify a single process to enter. - Cannot enter process {0} because it has not loaded the PowerShell engine. + Cannot enter process with Id '{0}' because it has not loaded the PowerShell engine. No process was found with Id: {0}.