WPF开发之C#中关闭进程的方式(Process)

根据名称关闭

命令关闭

在结束WPS进程的时候,process.Kill();并不能结束进程成功,使用命令结束是可以的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
using System;
using System.Diagnostics;
using System.Security.Principal;

public class ProcessUtils
{
/// <summary>
/// 传入进程名 不用带.exe
/// </summary>
/// <param name="name"></param>
public static void CloseProcessesByName(string name)
{
// 检查是否以管理员身份运行
if (!IsRunningAsAdmin())
{
Console.WriteLine("⚠️ 请以管理员身份运行本程序,否则可能无法结束某些进程。");
}

try
{
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = "taskkill",
Arguments = $"/f /t /im {name}.exe",
UseShellExecute = false, // 不使用操作系统 shell
RedirectStandardOutput = true, // 重定向标准输出(可选)
RedirectStandardError = true, // 重定向错误输出(可选)
CreateNoWindow = true // 不创建新窗口
};

using (Process process = Process.Start(startInfo))
{
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
process.WaitForExit();

if (process.ExitCode == 0)
{
Console.WriteLine($"成功终止 {name} 进程。");
Console.WriteLine("输出: \n" + output);
}
else
{
Console.WriteLine("终止失败,退出代码: " + process.ExitCode);
Console.WriteLine("错误信息: \n" + error);
}
}
}
catch (Exception ex)
{
Console.WriteLine("执行 taskkill 时发生异常: " + ex.Message);
}
}


static bool IsRunningAsAdmin()
{
try
{
var identity = WindowsIdentity.GetCurrent();
var principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
catch
{
return false;
}
}
}

Process

按名称结束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
using System;
using System.Diagnostics;
using System.Security.Principal;

public class ProcessUtils
{
/// <summary>
/// 传入进程名 不用带.exe
/// </summary>
/// <param name="name"></param>
public static void CloseProcessesByName(string name)
{
// 检查是否以管理员身份运行
if (!IsRunningAsAdmin())
{
Console.WriteLine("⚠️ 请以管理员身份运行本程序,否则可能无法结束某些进程。");
}


try
{
Process[] processes = Process.GetProcessesByName(name);

if (processes.Length == 0)
{
Console.WriteLine($@"没有找到 {name} 进程。");
return;
}

foreach (Process process in processes)
{
try
{
// 强制结束进程
process.Kill();

// 等待进程退出(最多等待3秒)
process.WaitForExit(3000);

Console.WriteLine($"已结束进程 ID: {process.Id}");
}
catch (Exception ex)
{
Console.WriteLine($"结束进程时出错 (ID: {process.Id}): {ex.Message}");
}
finally
{
// 释放资源
process.Dispose();
}
}
}
catch (Exception ex)
{
Console.WriteLine($"获取进程列表时出错: {ex.Message}");
}
}


static bool IsRunningAsAdmin()
{
try
{
var identity = WindowsIdentity.GetCurrent();
var principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
catch
{
return false;
}
}
}

按路径结束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private static void StopNginx()
{
Process[] processes = Process.GetProcessesByName("nginx");
foreach (Process p in processes)
{
string basePath = AppDomain.CurrentDomain.BaseDirectory;
string nginxPath = System.IO.Path.Combine(basePath, "Nginx", "nginx.exe");
if (nginxPath == p.MainModule.FileName)
{
p.Kill();
p.Close();
}
}
}

注意

进程名称不要写成nginx.exe,会找不到nginx进程。

本来我还尝试了用进程对象来结束,但是不行,因为Nginx启动会产生多个进程,单独结束掉一个是不行的!

根据端口号关闭

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace SchoolClient.Utils
{
internal class ZProcessUtil
{
public static void closeProcess(int port)
{
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.CreateNoWindow = true;
List<int> list_pid = GetPidByPort(p, port);
if (list_pid.Count == 0)
{
return;
}
List<string> list_process = GetProcessNameByPid(p, list_pid);
StringBuilder sb = new StringBuilder();
sb.AppendLine("占用" + port + "端口的进程有:");
foreach (var item in list_process)
{
sb.Append(item + "\r\n");
}
Console.WriteLine(sb.ToString());

PidKill(p, list_pid);
}

/// <summary>
/// 根据PID杀掉进程
/// </summary>
/// <param name="p"></param>
/// <param name="list_pid"></param>
private static void PidKill(Process p, List<int> list_pid)
{
p.Start();
foreach (var item in list_pid)
{
p.StandardInput.WriteLine("taskkill /pid " + item + " /f");
p.StandardInput.WriteLine("exit");
}
p.Close();
}

/// <summary>
/// 根据端口号获取进程ID
/// </summary>
/// <param name="p"></param>
/// <param name="port"></param>
/// <returns></returns>
private static List<int> GetPidByPort(Process p, int port)
{
int result;
bool b = true;
p.Start();
p.StandardInput.WriteLine(string.Format("netstat -ano|findstr {0}", port));
p.StandardInput.WriteLine("exit");
StreamReader reader = p.StandardOutput;
string strLine = reader.ReadLine();
List<int> list_pid = new List<int>();
while (!reader.EndOfStream)
{
strLine = strLine.Trim();
if (strLine.Length > 0 && ((strLine.Contains("TCP") || strLine.Contains("UDP"))))
{
Regex r = new Regex(@"\s+");
string[] strArr = r.Split(strLine);
if (strArr.Length >= 4)
{
b = int.TryParse(strArr[4], out result);
if (b && !list_pid.Contains(result))
list_pid.Add(result);
}
}
strLine = reader.ReadLine();
}
p.WaitForExit();
reader.Close();
p.Close();
return list_pid;
}

/// <summary>
/// 根据PID获取进程名
/// </summary>
/// <param name="p"></param>
/// <param name="list_pid"></param>
/// <returns></returns>
private static List<string> GetProcessNameByPid(Process p, List<int> list_pid)
{
p.Start();
List<string> list_process = new List<string>();
foreach (var pid in list_pid)
{
p.StandardInput.WriteLine(string.Format("tasklist |findstr \"{0}\"", pid));
p.StandardInput.WriteLine("exit");
StreamReader reader = p.StandardOutput;//截取输出流
string strLine = reader.ReadLine();//每次读取一行

while (!reader.EndOfStream)
{
strLine = strLine.Trim();
if (strLine.Length > 0 && ((strLine.Contains(".exe"))))
{
Regex r = new Regex(@"\s+");
string[] strArr = r.Split(strLine);
if (strArr.Length > 0)
{
list_process.Add(strArr[0]);
}
}
strLine = reader.ReadLine();
}
p.WaitForExit();
reader.Close();
}
p.Close();

return list_process;
}
}
}

其实就是用CMD获取占用端口的进程ID

1
netstat -ano|findstr ":10077 "

比如进程ID为16212

查看进程对应的进程名称

1
tasklist |findstr 16212

结束进程

1
taskkill /f /pid 16212