Process.Kill() 似乎没有终止进程
Process.Kill() doesn't seem to kill the process
我在使用 Process.Kill()
时遇到问题。我想我一定是误解了它是如何工作的。这是我的测试功能。我启动了一个长 运行 进程 (ping -t
),然后在五秒后将其终止。
我可以看到 ping 进程出现,但在我的程序完成后该进程仍然存在。我必须手动杀死它。
Console.WriteLine("Total number of ping processes is {0}", Process.GetProcessesByName("ping").Length);
ProcessStartInfo startInfo = new ProcessStartInfo("cmd.exe");
Process process = new Process();
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.Arguments = "/c ping -t 8.8.8.8";
Console.WriteLine("Staring ping process");
process.StartInfo = startInfo;
process.Start();
Thread.Sleep(5000);
Console.WriteLine("Total number of ping processes is {0}", Process.GetProcessesByName("ping").Length);
Thread.Sleep(5000);
Console.WriteLine("Killing ping process");
process.Kill();
Thread.Sleep(5000);
Console.WriteLine("Total number of ping processes is {0}", Process.GetProcessesByName("ping").Length);
我做错了什么?
In order to kill a process you have to run under an administrative
account. This means either that you are a 'true' administrator or you
User Account Control (UAC) turned off.
Otherwise Process.Kill() will fail.
来自 here.
process.Kill() 正在运行,只是不在您认为的过程中。您正在做的实际上是启动 2 个进程并且只终止第一个进程,而第二个进程保持 运行ning。
您拥有的代码正在启动一个新命令 shell 并将该进程信息保存到 process
。当你调用 process.Kill()
只有命令 shell 正在退出你可以 运行
Console.WriteLine(process.ProcessName);
在您 process.Kill()
之前查看哪个进程实际将被终止。通过将 \c ping -t 8.8.8.8
设置为命令 shell 的参数,您告诉命令 shell 启动另一个进程(在本例中为 ping)并将其与自身分离。您的程序不知道子进程,也不会杀死它。如果您真正想要的只是终止 ping 进程,您可以将代码更改为:
Console.WriteLine("Total number of ping processes is {0}", Process.GetProcessesByName("ping").Length);
ProcessStartInfo startInfo = new ProcessStartInfo("ping");
Process process = new Process();
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.Arguments = "-t 8.8.8.8";
Console.WriteLine("Staring ping process");
process.StartInfo = startInfo;
process.Start();
Thread.Sleep(5000);
Console.WriteLine("Total number of ping processes is {0}", Process.GetProcessesByName("ping").Length);
Thread.Sleep(5000);
Console.WriteLine("Killing ping process");
process.Kill();
Thread.Sleep(5000);
Console.WriteLine("Total number of ping processes is {0}", Process.GetProcessesByName("ping").Length);
但是,如果您确实需要首先启动命令 shell,您需要找到子进程并有逻辑来终止它。类似于:
foreach( var p in Process.GetProcessesByName("ping"))
{
p.Kill();
}
[编辑]
*抱歉,我一开始没有看到@Adriano Repetti 的评论。我不是故意要多余的。
您启动了 cmd.exe,然后 cmd.exe 启动了子进程 ping.exe。要杀死 ping.exe 你可以杀死所有进程层次结构。例如使用 WMI(添加 System.Management
参考):
private static void KillProcessAndChildrens(int pid)
{
ManagementObjectSearcher processSearcher = new ManagementObjectSearcher
("Select * From Win32_Process Where ParentProcessID=" + pid);
ManagementObjectCollection processCollection = processSearcher.Get();
try
{
Process proc = Process.GetProcessById(pid);
if (!proc.HasExited) proc.Kill();
}
catch (ArgumentException)
{
// Process already exited.
}
if (processCollection != null)
{
foreach (ManagementObject mo in processCollection)
{
KillProcessAndChildrens(Convert.ToInt32(mo["ProcessID"])); //kill child processes(also kills childrens of childrens etc.)
}
}
}
这是 答案的补丁,因为它的答案泄漏了子进程的子进程。
private static void KillProcessAndChildrens(int pid)
{
ManagementObjectSearcher processSearcher = new ManagementObjectSearcher
("Select * From Win32_Process Where ParentProcessID=" + pid);
ManagementObjectCollection processCollection = processSearcher.Get();
// We must kill child processes first!
if (processCollection != null)
{
foreach (ManagementObject mo in processCollection)
{
KillProcessAndChildrens(Convert.ToInt32(mo["ProcessID"])); //kill child processes(also kills childrens of childrens etc.)
}
}
// Then kill parents.
try
{
Process proc = Process.GetProcessById(pid);
if (!proc.HasExited) proc.Kill();
}
catch (ArgumentException)
{
// Process already exited.
}
}
FWIW Julio 修改的 VS2019 Visual Basic 版本。
Private Sub KillProcessAndChildrens(pintPID As Integer)
Dim processSearcher As New ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + pintPID.ToString)
Dim processCollection As ManagementObjectCollection = processSearcher.Get()
' We must kill child processes first!
If Not IsNothing(processCollection) Then
For Each mo As ManagementObject In processCollection
KillProcessAndChildrens(Convert.ToInt32(mo.Item("ProcessID")))
Next
End If
' // Then kill parents.
Try
Dim proc As Process = Process.GetProcessById(pintPID)
If Not proc.HasExited Then
proc.Kill()
End If
Catch ex As Exception
' Process already exited.
End Try
End Sub
我在使用 Process.Kill()
时遇到问题。我想我一定是误解了它是如何工作的。这是我的测试功能。我启动了一个长 运行 进程 (ping -t
),然后在五秒后将其终止。
我可以看到 ping 进程出现,但在我的程序完成后该进程仍然存在。我必须手动杀死它。
Console.WriteLine("Total number of ping processes is {0}", Process.GetProcessesByName("ping").Length);
ProcessStartInfo startInfo = new ProcessStartInfo("cmd.exe");
Process process = new Process();
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.Arguments = "/c ping -t 8.8.8.8";
Console.WriteLine("Staring ping process");
process.StartInfo = startInfo;
process.Start();
Thread.Sleep(5000);
Console.WriteLine("Total number of ping processes is {0}", Process.GetProcessesByName("ping").Length);
Thread.Sleep(5000);
Console.WriteLine("Killing ping process");
process.Kill();
Thread.Sleep(5000);
Console.WriteLine("Total number of ping processes is {0}", Process.GetProcessesByName("ping").Length);
我做错了什么?
In order to kill a process you have to run under an administrative account. This means either that you are a 'true' administrator or you User Account Control (UAC) turned off.
Otherwise Process.Kill() will fail.
来自 here.
process.Kill() 正在运行,只是不在您认为的过程中。您正在做的实际上是启动 2 个进程并且只终止第一个进程,而第二个进程保持 运行ning。
您拥有的代码正在启动一个新命令 shell 并将该进程信息保存到 process
。当你调用 process.Kill()
只有命令 shell 正在退出你可以 运行
Console.WriteLine(process.ProcessName);
在您 process.Kill()
之前查看哪个进程实际将被终止。通过将 \c ping -t 8.8.8.8
设置为命令 shell 的参数,您告诉命令 shell 启动另一个进程(在本例中为 ping)并将其与自身分离。您的程序不知道子进程,也不会杀死它。如果您真正想要的只是终止 ping 进程,您可以将代码更改为:
Console.WriteLine("Total number of ping processes is {0}", Process.GetProcessesByName("ping").Length);
ProcessStartInfo startInfo = new ProcessStartInfo("ping");
Process process = new Process();
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.Arguments = "-t 8.8.8.8";
Console.WriteLine("Staring ping process");
process.StartInfo = startInfo;
process.Start();
Thread.Sleep(5000);
Console.WriteLine("Total number of ping processes is {0}", Process.GetProcessesByName("ping").Length);
Thread.Sleep(5000);
Console.WriteLine("Killing ping process");
process.Kill();
Thread.Sleep(5000);
Console.WriteLine("Total number of ping processes is {0}", Process.GetProcessesByName("ping").Length);
但是,如果您确实需要首先启动命令 shell,您需要找到子进程并有逻辑来终止它。类似于:
foreach( var p in Process.GetProcessesByName("ping"))
{
p.Kill();
}
[编辑] *抱歉,我一开始没有看到@Adriano Repetti 的评论。我不是故意要多余的。
您启动了 cmd.exe,然后 cmd.exe 启动了子进程 ping.exe。要杀死 ping.exe 你可以杀死所有进程层次结构。例如使用 WMI(添加 System.Management
参考):
private static void KillProcessAndChildrens(int pid)
{
ManagementObjectSearcher processSearcher = new ManagementObjectSearcher
("Select * From Win32_Process Where ParentProcessID=" + pid);
ManagementObjectCollection processCollection = processSearcher.Get();
try
{
Process proc = Process.GetProcessById(pid);
if (!proc.HasExited) proc.Kill();
}
catch (ArgumentException)
{
// Process already exited.
}
if (processCollection != null)
{
foreach (ManagementObject mo in processCollection)
{
KillProcessAndChildrens(Convert.ToInt32(mo["ProcessID"])); //kill child processes(also kills childrens of childrens etc.)
}
}
}
这是
private static void KillProcessAndChildrens(int pid)
{
ManagementObjectSearcher processSearcher = new ManagementObjectSearcher
("Select * From Win32_Process Where ParentProcessID=" + pid);
ManagementObjectCollection processCollection = processSearcher.Get();
// We must kill child processes first!
if (processCollection != null)
{
foreach (ManagementObject mo in processCollection)
{
KillProcessAndChildrens(Convert.ToInt32(mo["ProcessID"])); //kill child processes(also kills childrens of childrens etc.)
}
}
// Then kill parents.
try
{
Process proc = Process.GetProcessById(pid);
if (!proc.HasExited) proc.Kill();
}
catch (ArgumentException)
{
// Process already exited.
}
}
FWIW Julio 修改的 VS2019 Visual Basic 版本。
Private Sub KillProcessAndChildrens(pintPID As Integer)
Dim processSearcher As New ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + pintPID.ToString)
Dim processCollection As ManagementObjectCollection = processSearcher.Get()
' We must kill child processes first!
If Not IsNothing(processCollection) Then
For Each mo As ManagementObject In processCollection
KillProcessAndChildrens(Convert.ToInt32(mo.Item("ProcessID")))
Next
End If
' // Then kill parents.
Try
Dim proc As Process = Process.GetProcessById(pintPID)
If Not proc.HasExited Then
proc.Kill()
End If
Catch ex As Exception
' Process already exited.
End Try
End Sub