在运行SpringBoot程序时,有时会因为对应端口被占用导致程序运行失败,打开cmd杀死对应的进程太过于麻烦,所以写了该程序,java不够熟练,所以选择了熟练的c#语言来写该程序,使用的环境为:.net 6。
该程序功能实现是这样的:通过调用cmd程序,并根据用户输入的对应的IP地址或者是端口号杀死对应的进程。该程序使用到的cmd命令适用于win11,老系统是否支持就不太清楚了。
第一步,先调用cmd程序,并执行对应的命令,代码如下:(该代码从网上抄的,略加修改,该代码涉及到动态类型dynamic和可选参数,不懂的同学可以百度查询一下)
public static dynamic RunCmd(string cmd,bool isReturnStreamReader=false)
{
Process pro = new Process();
pro.StartInfo.FileName = "cmd.exe";
pro.StartInfo.CreateNoWindow = true; // 不创建新窗口
pro.StartInfo.UseShellExecute = false; //不启用shell启动进程
pro.StartInfo.RedirectStandardInput = true; // 重定向输入
pro.StartInfo.RedirectStandardOutput = true; // 重定向标准输出
pro.StartInfo.RedirectStandardError = true;
pro.StartInfo.StandardErrorEncoding = System.Text.UTF8Encoding.UTF8;
pro.StartInfo.StandardOutputEncoding = System.Text.UTF8Encoding.UTF8;
// 重定向错误输出
// pro.StartInfo.WorkingDirectory = path;
pro.Start();//开启cmd
pro.StandardInput.WriteLine(cmd);
pro.StandardInput.AutoFlush = true;
pro.StandardInput.WriteLine("exit"); //若是运行时间短可加入此命令
dynamic output;
if (isReturnStreamReader)
{
output = pro.StandardOutput;
}
else
{
output = pro.StandardOutput.ReadToEnd();
}
pro.WaitForExit();//若运行时间长,使用这个,等待程序执行完退出进程
pro.Close();
return output;
}
之后我们调用cmd获取对应ip或者端口号的所有进程信息,使用命令"netstat -aon|findstr 地址或者端口号"即可获取,获取PID代码如下:
public static List<string> GetPidOfAddress(string address)
{
//用来保存所有对应地址的端口号数据
List<string> valueList = new List<string>();
//获取返回的StreamReader数据
StreamReader sr = RunCmd($"netstat -aon|findstr {address}", true);
//读取StreamReader的每一行数据
while (!sr.EndOfStream)
{
string value = sr.ReadLine();
//查看当前读取的行中内容是否包含TCP字符
if (!string.IsNullOrEmpty(value) && value.Contains("TCP"))
{
//只获取状态为 LISTENING 的数据
string[] ss = value.Split("LISTENING");
//获取端口号数据信息
if (ss.Length >= 2)
{
string port = ss[ss.Length - 1].Trim();
//重复的端口号不加入结果列表中
if (valueList.FirstOrDefault(a => a == port) == null)
valueList.Add(port);
}
}
}
return valueList;
}
我们可以从获取到的进程信息中获取到对应的pid信息,并使用"taskkill /F /pid 进程的PID"命令杀死对应进程,代码如下:
/// <summary>
/// 根据PID杀死对应进程
/// </summary>
/// <param name="pid"></param>
/// <returns></returns>
public static string KillTask(string pid)
{
return RunCmd($"taskkill /F /pid {pid}");
}
以上代码我均放在CmdHelper类中,在mian函数中调用如下:
Console.WriteLine("请输入对应的地址或者端口号");
string addressOrPort = Console.ReadLine();
//如果用户输入空则将目标设置为8888端口,即0.0.0.0:8888
if (string.IsNullOrEmpty(addressOrPort))
{
addressOrPort = "0.0.0.0:8888";
}
Console.WriteLine($"当前你要杀死的进程的地址或端口号为:{addressOrPort}");
Console.WriteLine("\n查询到的进程如下:");
Console.WriteLine(CmdHelper.ListTcp(addressOrPort));
//Console.WriteLine("\n当前要杀死的进程的PID为:");
List<string> pidList = CmdHelper.GetPidOfAddress(addressOrPort);
foreach (string item in pidList)
{
Console.WriteLine($"{item}");
CmdHelper.KillTask(item);
Console.WriteLine("已经杀死进程" + item);
}
Console.WriteLine();
Console.WriteLine("按任意键退出程序");
Console.ReadKey();
运行完成之后,对应端口的spring boot程序也结束了运行,效果还行,以后不用费劲的打开cmd慢慢整了。提示:pid为0的进程好像是系统进程是不能杀死的。