前言
为啥要开发这个呢 ,系统自带的关闭有些程序就关不了,它有好多线程,你关一其中一个它后台又重新开了一个,关不完,使用我这个呢 就把所有相同名称进程看作一个,一关就关
下载软件
v1
Form1.cs
using System;
using System.Windows.Forms;namespace TaskMaster
{public partial class Form1 : Form{// 全局变量用于跟踪上次点击的列和排序方向private DataGridViewColumn lastSortedColumn;private SortOrder lastSortOrder = SortOrder.None;TaskManager taskManager;public Form1(){InitializeComponent();// 实例化 TaskManagertaskManager = new TaskManager();//设置 DataGridView 的 Anchor 属性,确保它的大小会根据窗体的大小进行调整。你可以将 Anchor 设置为四个方向,使其随着窗口的拉伸或缩小进行动态调整。dataGridView1.Anchor = (AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right);// 将进程信息加载到 dataGridView1taskManager.LoadProcessesIntoDataGridView(dataGridView1);// 绑定列头点击事件用于自定义排序dataGridView1.ColumnHeaderMouseClick += DataGridView_ColumnHeaderMouseClick;}/// <summary>/// 刷新/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void button1_Click(object sender, EventArgs e){// 将进程信息加载到 dataGridView1taskManager.LoadProcessesIntoDataGridView(dataGridView1);}/// <summary>/// 检查是否右键点击/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void dataGridView1_MouseDown(object sender, MouseEventArgs e){// 检查是否右键点击if (e.Button == MouseButtons.Right){var hitTestInfo = dataGridView1.HitTest(e.X, e.Y);if (hitTestInfo.RowIndex >= 0){// 选中行dataGridView1.Rows[hitTestInfo.RowIndex].Selected = true;// 动态创建并显示上下文菜单ContextMenuStrip contextMenu = new ContextMenuStrip();ToolStripMenuItem closeProcessItem = new ToolStripMenuItem("关闭进程");closeProcessItem.Click += CloseProcessItem_Click;contextMenu.Items.Add(closeProcessItem);contextMenu.Show(dataGridView1, e.Location);}}}/// <summary>/// 点击终止进程/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void CloseProcessItem_Click(object sender, EventArgs e){// 获取选中行的进程名称if (dataGridView1.SelectedRows.Count > 0){var selectedRow = dataGridView1.SelectedRows[0];string processName = selectedRow.Cells["ProcessName"].Value.ToString();// 终止进程taskManager.KillProcessesByName(processName);// 重新加载进程列表taskManager.LoadProcessesIntoDataGridView(dataGridView1);}}// 列头点击事件,用于自定义排序private void DataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e){DataGridView dataGridView = sender as DataGridView;// 获取当前点击的列DataGridViewColumn clickedColumn = dataGridView.Columns[e.ColumnIndex];// 如果点击的是上次排序的列,切换排序方向SortOrder sortOrder;if (clickedColumn == lastSortedColumn){sortOrder = lastSortOrder == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending;}else{// 如果是新列,默认升序排序sortOrder = SortOrder.Ascending;}// 根据列名执行不同的自定义排序逻辑if (clickedColumn.Name == "MemoryUsage"){dataGridView.Sort(new MemoryUsageComparer());}else if (clickedColumn.Name == "CpuTime"){dataGridView.Sort(new CpuTimeComparer());}else{// 默认的列使用内置排序dataGridView.Sort(clickedColumn, sortOrder == SortOrder.Ascending? System.ComponentModel.ListSortDirection.Ascending: System.ComponentModel.ListSortDirection.Descending);}// 保存当前排序的列和方向lastSortedColumn = clickedColumn;lastSortOrder = sortOrder;}}}
TaskManager.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;namespace TaskMaster
{public class TaskManager{// 获取所有正在运行的进程并直接绑定到传入的 DataGridViewpublic void LoadProcessesIntoDataGridView(DataGridView dataGridView){// 清除现有的数据dataGridView.Rows.Clear();dataGridView.Columns.Clear();// 设置 DataGridView 属性dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;dataGridView.AllowUserToAddRows = false;dataGridView.RowTemplate.Height = 50;// 创建一个新的 DataGridViewImageColumnDataGridViewImageColumn imageColumn = new DataGridViewImageColumn{HeaderText = "图标",Name = "IconColumn",ImageLayout = DataGridViewImageCellLayout.Normal};dataGridView.Columns.Add(imageColumn);// 添加其他数据列dataGridView.Columns.Add("ProcessName", "进程名");dataGridView.Columns.Add("PID", "进程ID");dataGridView.Columns.Add("MemoryUsage", "内存使用 (KB)");dataGridView.Columns.Add("CpuTime", "CPU时间");// 用于存储已经显示的进程名称HashSet<string> displayedProcesses = new HashSet<string>();// 获取所有进程Process[] processes = Process.GetProcesses();foreach (var process in processes){try{// 只显示尚未显示的进程if (!displayedProcesses.Contains(process.ProcessName)){// 获取进程的可执行文件路径string filePath = process.MainModule.FileName;// 获取进程图标Icon processIcon = GetProcessIcon(filePath);Bitmap iconBitmap = processIcon.ToBitmap();// 创建新行并设置图像及其他数据int rowIndex = dataGridView.Rows.Add();DataGridViewRow row = dataGridView.Rows[rowIndex];row.Cells["IconColumn"].Value = iconBitmap;row.Cells["ProcessName"].Value = process.ProcessName;row.Cells["PID"].Value = process.Id;row.Cells["MemoryUsage"].Value = FormatMemorySize(process.WorkingSet64);row.Cells["CpuTime"].Value = FormatCpuTime(process.TotalProcessorTime);// 记录已显示的进程名displayedProcesses.Add(process.ProcessName);}}catch (Exception ex){Console.WriteLine($"无法读取进程 {process.ProcessName}: {ex.Message}");}}}/// <summary>/// 格式化 CPU 时间,如果小时或分钟为 0 则不显示它们/// </summary>/// <param name="cpuTime"></param>/// <returns></returns>private string FormatCpuTime(TimeSpan cpuTime){int hours = cpuTime.Hours;int minutes = cpuTime.Minutes;int seconds = cpuTime.Seconds;int milliseconds = cpuTime.Milliseconds;// 使用 StringBuilder 动态构建时间字符串StringBuilder formattedTime = new StringBuilder();if (hours > 0){formattedTime.Append($"{hours}H");}if (minutes > 0 || hours > 0) // 如果有小时,即使分钟为 0 也显示{formattedTime.Append($"{minutes}M");}if (seconds > 0 || minutes > 0 || hours > 0) // 如果有分钟或小时,即使秒为 0 也显示{formattedTime.Append($"{seconds}S");}// 毫秒总是显示formattedTime.Append($"{milliseconds}MS");return formattedTime.ToString();}/// <summary>/// 将内存大小转换为合适的单位/// </summary>/// <param name="bytes"></param>/// <returns></returns>private string FormatMemorySize(long bytes){const double KB = 1024;const double MB = KB * 1024;const double GB = MB * 1024;if (bytes >= GB){return $"{(bytes / GB):F2} GB";}else if (bytes >= MB){return $"{(bytes / MB):F2} MB";}else if (bytes >= KB){return $"{(bytes / KB):F2} KB";}else{return $"{bytes} B";}}/// <summary>/// 获取进程图标/// </summary>/// <param name="filePath"></param>/// <returns></returns>private Icon GetProcessIcon(string filePath){try{// 使用 Icon.ExtractAssociatedIcon 方法获取文件图标return Icon.ExtractAssociatedIcon(filePath);}catch{// 如果获取图标失败,返回一个默认图标return SystemIcons.Application; // 使用默认图标}}// 根据进程 ID 终止进程public bool KillProcess(int processId){try{Process process = Process.GetProcessById(processId);process.Kill();return true;}catch (Exception ex){Console.WriteLine($"无法终止进程 {processId}: {ex.Message}");return false;}}// 根据进程名称终止所有匹配的进程public bool KillProcessesByName(string processName){try{// 查找所有与指定名称匹配的进程Process[] processes = Process.GetProcessesByName(processName);if (processes.Length == 0){Console.WriteLine($"没有找到名为 {processName} 的进程。");return false;}// 终止所有匹配的进程foreach (var process in processes){process.Kill();}Console.WriteLine($"已终止所有名为 {processName} 的进程。");return true;}catch (Exception ex){Console.WriteLine($"无法终止进程 {processName}: {ex.Message}");return false;}}}
}
工程源码
v1