You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hard to say if this is a PowerShell or a .NET issue... Can you swap the final step for [System.Diagnostics.Process]::GetProcessById($proc.Id) and see if you get the same?
We may need to file an issue in the dotnet repository if it still reproduces with only .NET code.
Interesting... The documentation for the Process class mentions that calling Process.Kill() is asynchronous, and if you want to wait for a process to fully exit you can check Process.HasExited or use Process.WaitForExit()
Looking at the Stop-Process cmdlet code, it looks like it will pretty much always just call Process.Kill() and move on.
I'm not entirely sure it makes sense for the cmdlet to always wait for each process to exit. It would cause problems if you were passing an array of processes to stop, and a particular process didn't exit, preventing the cmdlet from terminating subsequent processes.
If anything, I'd suggest we enhance Stop-Process to support:
A -Wait switch to wait for the process(es) to exit, and
A -WaitTimeout parameter to specify a number of seconds (maybe 3-5 seconds by default?) to wait for process terminations to complete.
The cmdlet can call Kill() on all the processes, and then wait in a loop with small sleeps in EndProcessing() until either the timeout has elapsed or all processes have exited. If the timeout elapses and some or all processes have not yet terminated, write non-terminating errors for each process that failed to stop.
This is a .NET Core bug, mentioned in dotnet/runtime#20725 (comment) and presumably caused by dotnet/corefx#17476, i.e. between .NET Core 1.1.13 and 2.0.0. On .NET Framework 4.8, Process.GetProcessById does not return a process that has already terminated, even if the process object still exists because of process handles.
using System;
using System.Diagnostics;
using System.Threading;
namespace ProcessTest
{
class Program
{
static void Main(string[] args)
{
Process testproc = Process.Start(@"C:\\Program Files\\Notepad++\notepad++");
Console.WriteLine($"Started a new process with ID {testproc.Id}");
Console.WriteLine($"Get process by id {Process.GetProcessById(testproc.Id).ProcessName}");
testproc.Kill();
Console.WriteLine($"Process with Id {testproc.Id} was killed");
Thread.Sleep(5000);
try
{
Console.WriteLine($"Get process by id {Process.GetProcessById(testproc.Id).ProcessName}");
}
catch (Exception e) {
Console.WriteLine($"GetProcessById filed with Exception: {e.Message}");
}
}
}
}
On .Net Core 2.1 and .net core 3.1 i received a next:
Started a new process with ID 9896
Get process by id notepad++
Process with Id 9896 was killed
GetProcessById filed with Exception: Process has exited, so the requested information is not available.
GetProcessByID works correctly with killed process in actual .net core version.
Started a new process with ID 9896
Get process by id notepad++
Process with Id 9896 was killed
GetProcessById filed with Exception: Process has exited, so the requested information is not available.
That exception comes from Process.ProcessName, not Process.GetProcessById.
It is Windows behavior that OpenProcess can open a process that has already terminated. Process.GetProcessById tries to detect that situation and throw ArgumentException, but the detection no longer works in .NET Core.
A PowerShell script that uses Get-Process can work around the bug by checking Process.HasExited, which has the correct value. Alternatively, Get-Process could be changed to do that.
dotnet/runtime#63937 was fixed in .NET v7.0.0-preview.3.22175.4. #17061 updated to .NET SDK 7.0.100-preview.4.22252.9. When PowerShell v7.3.0-preview.4 is released, it should include the fix.
Activity
vexx32 commentedon Jun 3, 2020
This might just be a timing issue, retrieving the process before it's finished shutting down. Killing a process isn't always instantaneous.
Does it still reproduce if you have a slight wait before calling the final Get-Process?
Sidoran commentedon Jun 3, 2020
This issue are reproduced after a several minutes wait.
Return the same.
On powershell 5.1 everything works fine
vexx32 commentedon Jun 3, 2020
Interesting. I'm not seeing the same on MacOS.
Hard to say if this is a PowerShell or a .NET issue... Can you swap the final step for
[System.Diagnostics.Process]::GetProcessById($proc.Id)and see if you get the same?We may need to file an issue in the dotnet repository if it still reproduces with only .NET code.
Sidoran commentedon Jun 3, 2020
return the same:
This issue was first found on Windows Server 2012R2
vexx32 commentedon Jun 3, 2020
Interesting... The documentation for the Process class mentions that calling
Process.Kill()is asynchronous, and if you want to wait for a process to fully exit you can checkProcess.HasExitedor useProcess.WaitForExit()Looking at the Stop-Process cmdlet code, it looks like it will pretty much always just call
Process.Kill()and move on.I'm not entirely sure it makes sense for the cmdlet to always wait for each process to exit. It would cause problems if you were passing an array of processes to stop, and a particular process didn't exit, preventing the cmdlet from terminating subsequent processes.
If anything, I'd suggest we enhance
Stop-Processto support:-Waitswitch to wait for the process(es) to exit, and-WaitTimeoutparameter to specify a number of seconds (maybe 3-5 seconds by default?) to wait for process terminations to complete.The cmdlet can call
Kill()on all the processes, and then wait in a loop with small sleeps inEndProcessing()until either the timeout has elapsed or all processes have exited. If the timeout elapses and some or all processes have not yet terminated, write non-terminating errors for each process that failed to stop.iSazonov commentedon Jun 3, 2020
We get the info from Process.GetProcessById(). So I think it is Windows behavior.
You can ask in .Net Runtime repository about this.
KalleOlaviNiemitalo commentedon Jun 5, 2020
This is a .NET Core bug, mentioned in dotnet/runtime#20725 (comment) and presumably caused by dotnet/corefx#17476, i.e. between .NET Core 1.1.13 and 2.0.0. On .NET Framework 4.8,
Process.GetProcessByIddoes not return a process that has already terminated, even if the process object still exists because of process handles.Process.UpdateHasExiteduses a zero-duration wait on the process handle to check whether the process has terminated.ProcessManager.IsProcessRunningshould be changed to do the same.Sidoran commentedon Jun 6, 2020
I writed a small console app
On .Net Core 2.1 and .net core 3.1 i received a next:
GetProcessByID works correctly with killed process in actual .net core version.
KalleOlaviNiemitalo commentedon Jun 6, 2020
That exception comes from
Process.ProcessName, notProcess.GetProcessById.KalleOlaviNiemitalo commentedon Jun 7, 2020
It is Windows behavior that OpenProcess can open a process that has already terminated. Process.GetProcessById tries to detect that situation and throw
ArgumentException, but the detection no longer works in .NET Core.A PowerShell script that uses Get-Process can work around the bug by checking Process.HasExited, which has the correct value. Alternatively,
Get-Processcould be changed to do that.TishSerg commentedon May 23, 2022
Hi. I just stumbled upon this nasty behavior of PowerShell 7.2.3.
And like in the case of topicstarter:
OS: Microsoft Windows [Version 10.0.19044.1706]
KalleOlaviNiemitalo commentedon May 23, 2022
dotnet/runtime#63937 was fixed in .NET v7.0.0-preview.3.22175.4. #17061 updated to .NET SDK 7.0.100-preview.4.22252.9. When PowerShell v7.3.0-preview.4 is released, it should include the fix.