首页/新闻资讯/正文详情

C#+WPF进程管理源码实战:从枚举到增量刷新

发布时间:2026/9/28 1:13:27 来源:云帆数科 栏目:资讯中心
C#+WPF进程管理源码实战:从枚举到增量刷新
简介这是一份基于C#与WPF框架开发的桌面应用进程管理程序源码面向计算机、自动化等相关专业的学生及开发者可用于课程设计、大作业或毕业设计参考也适合希望学习WPF桌面开发与进程操作技术的入门者。压缩包共17个文件约25KB以cs源码文件为主配合xaml界面文件、sln解决方案、csproj项目文件及配置文件等结构完整可直接在Visual Studio中打开运行。程序核心功能包括对可执行文件的启动、停止、显示、隐藏与重启操作通过ProcessObject等类封装进程管理逻辑界面与业务代码分离清晰便于理解WPF的数据绑定与事件处理机制。该资源为个人毕设项目评审分达95分经过严格调试确保可运行已有338人学习下载。读者可借此掌握进程管理类桌面应用的完整实现思路并在此基础上修改调整扩展出类似功能。1. 从一份 C#WPF 进程管理源码说起桌面端到底需要什么样的进程工具任务管理器已经足够好用为什么还有人愿意花时间用 C# 和 WPF 重写一个进程管理程序这个问题我在第一次拿到类似源码时也问过自己。真实场景往往不是「替代任务管理器」而是把它嵌进自己的桌面端应用里上位机需要监控采集进程有没有假死安装器需要在升级前确认目标进程已经退出企业内网工具需要按白名单限制员工机器上不该出现的程序。这些需求用现成工具都做不干净只能自己写一个带 UI 的进程管理模块而 C# 加 WPF 恰好是 Windows 桌面端最顺手的组合。这份源码的价值不在于界面多花哨而在于它把「枚举进程、读取信息、结束进程、刷新列表」这条链路用 WPF 的数据绑定串了起来能直接当模板改。适合两类人一是刚学完 C# 基础、想找一个有真实系统调用的练手项目的开发者二是手上有个上位机或运维工具需要快速补一块进程监控面板的工程师。下面我按「先讲清原理和选型再落到能跑的代码最后说坑」的顺序拆开讲。2. 进程管理模块的技术选型为什么是 C# 加 WPF 而不是 WinForm2.1 Process 类能拿到什么拿不到什么.NET 里操作进程的核心是System.Diagnostics.Process。它能给你进程 Id、进程名、是否响应、启动时间、占用内存、主窗口标题、可执行文件路径这些足够撑起一个管理面板。但它拿不到的东西同样要提前知道CPU 占用率不是直接属性得靠PerformanceCounter或者两次采样算差值进程的完整命令行参数在 .NET Core 之后才通过Process.GetProcesses拿不到需要 WMI 或NtQueryInformationProcess这类更底层的手段至于进程所属用户、父进程 Id同样要绕道 WMI。所以选型的第一层判断是你要做的是「轻量监控面板」还是「类任务管理器」。前者用Process类加定时刷新就够了后者必须引入System.Management查 WMI。这份源码属于前者它的定位是嵌入到别的应用里做辅助面板不是做一个全能工具。想清楚这一点后面很多取舍就顺了。2.2 WPF 的数据绑定为什么比 WinForm 更适合进程列表进程列表的本质是「一个会高频变化的数据集合」。WinForm 里你通常得手动清空ListView再逐条Add刷新频繁时界面闪烁、选中项丢失是家常便饭。WPF 的ObservableCollectionT配合DataGrid或ListView集合变化会自动通知 UI配合INotifyPropertyChanged连单个进程的内存数值变化都能自动更新不用碰任何控件。这就是选 WPF 的核心理由进程管理天然是数据驱动的场景而 WPF 的绑定机制就是为这种场景设计的。代价是学习曲线DataTemplate、IValueConverter、Dispatcher这些概念对新手不友好。但一旦跨过去后面加排序、筛选、分组都是改 XAML 的事不用重写逻辑。如果你只是想要一个能跑的窗口WinForm 更快如果你预期这个面板会持续迭代WPF 的长期成本更低。2.3 项目结构怎么拆才不返工我一般把这类项目拆成三层Models放进程数据模型Services放所有Process和 WMI 调用ViewModels放绑定逻辑和刷新调度。UI 层只认 ViewModel绝不直接在MainWindow.xaml.cs里写Process.GetProcesses()。这样拆的好处是将来要把进程数据源从本地换成远程 Agent 上报只改 Service 层UI 一行不动。// Models/ProcessInfo.cs public class ProcessInfo : INotifyPropertyChanged { public int Id { get; set; } public string Name { get; set; } private long _memoryMb; public long MemoryMb { get _memoryMb; set { _memoryMb value; OnPropertyChanged(nameof(MemoryMb)); } } public bool IsResponding { get; set; } public DateTime? StartTime { get; set; } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string name) PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); }这段模型类实现了INotifyPropertyChanged关键在MemoryMb这个属性。进程内存是刷新时变化最频繁的字段把它做成带通知的属性UI 上绑定的那一列就会自动更新不需要重建整个列表。Id、Name这类不常变的字段用普通属性即可减少通知开销。注意StartTime用可空类型因为部分系统进程拿不到启动时间直接访问会抛异常。3. 用 Process 类把进程列表跑起来枚举、刷新与结束的最小实现3.1 枚举进程并转成可绑定集合第一步是把系统里的进程读出来转成上一步定义的ProcessInfo集合。这里有个容易忽略的点Process.GetProcesses()返回的Process对象是IDisposable用完不释放会累积句柄长时间运行的工具迟早出问题。// Services/ProcessService.cs public ListProcessInfo GetAllProcesses() { var result new ListProcessInfo(); var processes Process.GetProcesses(); foreach (var p in processes) { try { result.Add(new ProcessInfo { Id p.Id, Name p.ProcessName, MemoryMb p.WorkingSet64 / 1024 / 1024, IsResponding p.Responding, StartTime TryGetStartTime(p) }); } catch (Exception) { // 系统进程或已退出进程会抛异常跳过即可 } finally { p.Dispose(); } } return result; } private DateTime? TryGetStartTime(Process p) { try { return p.StartTime; } catch { return null; } }逻辑上分三步遍历、逐个取值、释放。try-catch不是偷懒是必须的——系统进程和刚退出的进程访问属性会抛Win32Exception或InvalidOperationException不捕获整个刷新就崩了。WorkingSet64是物理内存工作集除以两次 1024 得到 MB。TryGetStartTime单独抽出来是因为StartTime抛异常的概率比其他属性高隔离处理更清晰。参数上没什么可调的但要注意GetProcesses()不带参数是取本机全部进程如果只想取有主窗口的可以加p.MainWindowHandle ! IntPtr.Zero过滤。3.2 定时刷新与 UI 线程调度进程列表要定时刷新但刷新不能阻塞 UI 线程也不能在后台线程直接改ObservableCollection否则会抛「集合被另一个线程修改」的异常。正确做法是用DispatcherTimer它的 Tick 回调本身就在 UI 线程上。// ViewModels/MainViewModel.cs private readonly DispatcherTimer _timer; private readonly ProcessService _service new ProcessService(); public ObservableCollectionProcessInfo Processes { get; } new(); public MainViewModel() { _timer new DispatcherTimer { Interval TimeSpan.FromSeconds(2) }; _timer.Tick (s, e) Refresh(); _timer.Start(); } private void Refresh() { var latest _service.GetAllProcesses(); // 简单策略整体替换适合进程数不多的场景 Processes.Clear(); foreach (var item in latest) Processes.Add(item); }DispatcherTimer的Interval设成 2 秒是个经验值。设成 500 毫秒进程多的时候枚举本身就要几百毫秒UI 会卡设成 10 秒用户点了结束进程后要等很久列表才更新体验差。2 秒是流畅度和开销的平衡点。这里的刷新策略是整体清空重建实现简单但有个副作用用户选中的行会丢失。进程数在 200 以内时这个策略够用超过之后建议改成按 Id 做增量更新只更新变化的字段避免Clear引起的界面闪烁。3.3 结束进程与权限边界结束进程看起来就一行p.Kill()但实际会翻车的地方不少。权限不够、进程受保护、进程已经退出三种情况抛的异常都不一样。public bool KillProcess(int pid, out string message) { try { var p Process.GetProcessById(pid); p.Kill(); p.WaitForExit(3000); // 最多等 3 秒 message 已结束; return true; } catch (ArgumentException) { message 进程已不存在; return false; } catch (Win32Exception ex) { message $权限不足或被系统保护{ex.Message}; return false; } }GetProcessById在进程已退出时抛ArgumentException这是最常见的「点了结束但进程早没了」的情况。Kill()抛Win32Exception基本就是权限问题普通用户结束系统进程或别的用户会话下的进程都会撞上。WaitForExit(3000)给一个超时避免某些进程卡住导致 UI 假死。如果你的工具需要结束高权限进程唯一正路是让整个程序以管理员身份运行在app.manifest里声明requireAdministrator而不是在代码里想办法提权。4. 进程管理程序的避坑清单五个真实踩过的坑4.1 刷新时句柄泄漏导致内存持续上涨现象程序开着不动任务管理器里自己这个进程的内存每隔几分钟涨一点跑一晚上涨到几百 MB。原因就是Process.GetProcesses()返回的对象没Dispose每个Process对象背后握着一个系统句柄句柄不释放关联的内核对象和内存就回收不了。解决就是在遍历时用try-finally保证每个p.Dispose()都执行或者用using。这个坑在短时间测试时完全看不出来只有长时间运行才暴露属于典型的血泪经验。4.2 在后台线程更新 ObservableCollection 直接崩溃现象把刷新逻辑放到Task.Run里界面随机抛「This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread」。原因是ObservableCollection不是线程安全的WPF 的绑定系统要求集合变更必须发生在 UI 线程。解决有两条路一是用DispatcherTimer让刷新天然在 UI 线程二是坚持后台线程的话用Application.Current.Dispatcher.Invoke把集合操作包起来。我一般选前者代码更干净。4.3 拿 CPU 占用率时 PerformanceCounter 首次调用极慢现象想给列表加一列 CPU 占用用PerformanceCounter读% Processor Time第一次调用要等一两秒界面明显卡顿。原因是PerformanceCounter首次访问要加载性能计数器库。解决是提前在程序启动时预热一次或者干脆放弃实时 CPU改成用两次采样的TotalProcessorTime差值自己算。后者更可控也不依赖性能计数器库是否损坏——那玩意儿损坏是 Windows 上出了名的玄学问题。4.4 结束进程后列表没更新用户以为没生效现象点了结束进程实际已经死了但列表里还挂着用户反复点。原因是刷新是定时触发的结束操作后没立即刷新。解决是在KillProcess成功后手动调一次Refresh()给用户即时反馈。更进一步可以在结束前把该行标记成「正在结束」的灰色状态避免用户重复点击。这类交互细节不影响功能但直接影响别人对这个工具的评价。4.5 以管理员运行时拖拽文件失效现象程序用管理员权限运行后从资源管理器往窗口里拖文件没反应。原因是 Windows 的 UAC 机制下普通权限的 explorer.exe 无法向高权限进程发送拖拽消息。解决是如果不需要拖拽功能就别开管理员如果既要管理员又要拖拽得改注册表EnableLUA相关设置或调用ChangeWindowMessageFilterEx放行WM_DROPFILES消息。这个坑很隐蔽因为功能本身没问题是权限隔离导致的。5. 把进程面板做成可复用的监控组件增量刷新与状态标记前面讲的整体替换刷新进程数一多就露馅。我后来改成按 Id 做增量更新思路是维护一个Dictionaryint, ProcessInfo每次刷新时对比新旧集合新出现的进程加进去消失的移除还在的只更新变化字段。这样ObservableCollection的变更事件数量从「全部」降到「实际变化的那几个」界面几乎不闪。private readonly Dictionaryint, ProcessInfo _cache new(); private void RefreshIncremental() { var latest _service.GetAllProcesses(); var latestIds latest.Select(x x.Id).ToHashSet(); // 移除已退出的 foreach (var id in _cache.Keys.ToList()) { if (!latestIds.Contains(id)) { Processes.Remove(_cache[id]); _cache.Remove(id); } } // 新增或更新 foreach (var item in latest) { if (_cache.TryGetValue(item.Id, out var existing)) { existing.MemoryMb item.MemoryMb; // 触发通知UI 自动更新 existing.IsResponding item.IsResponding; } else { _cache[item.Id] item; Processes.Add(item); } } }关键在existing.MemoryMb item.MemoryMb这一行。因为MemoryMb是带INotifyPropertyChanged的属性赋值就会通知 UI 更新那一格不需要动集合。Processes只在进程真正增减时才变选中状态自然保住了。这个模式在监控类界面上是通用解法值得记住。再往上走一步可以给ProcessInfo加一个Status枚举把「正常 / 无响应 / 即将结束」标出来配合IValueConverter在DataGrid里显示不同颜色。无响应的判断用IsResponding但要注意这个属性对没有消息循环的进程比如控制台程序恒为 true别拿它当万能健康指标。我自己的习惯是任何监控面板都要留一个「导出当前快照到 CSV」的按钮出问题时用户能直接把现场发给你比让他截图描述强一百倍。这个习惯帮我省过很多来回扯皮的时间希望帮到你。本文还有配套的精品资源点击获取

相关推荐

新手入门避坑:wpf可以应用于网站开发吗?3招搞定
新手入门避坑:wpf可以应用于网站开发吗?3招搞定

新手入门避坑:wpf可以应用于网站开发吗?3招搞定 找建站公司,最怕啥?不是怕慢,是怕被当成“猪”宰。你心里没底,对方报价一万,你觉得贵;对方报价三千,你心里更慌,这钱花得冤不冤?很多老板第一次接触网站开发,就像盲人摸象,听到“wpf可以应… · 2026/9/28 1:13:27

Python智能医疗系统实战:数据库、可视化与诊断预测全流程
Python智能医疗系统实战:数据库、可视化与诊断预测全流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/28 1:13:14

焊接缺陷检测:6类2684张YOLO+VOC双格式数据集实战指南
焊接缺陷检测:6类2684张YOLO+VOC双格式数据集实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/28 1:13:08

Python搭建QQ聊天机器人极简教程
Python搭建QQ聊天机器人极简教程

随着QQ粉丝群管理需求的不断增长,简单的群管工具难以满足复杂的信息响应和自动化需求。现有的自动回复机器人虽然功能强大,但其高昂的年费成为不少用户的顾虑。因此,通过搭建一个自定义机器人来实现自动回复,成为解决这一问题的有效途径。 基于此需求,本文介绍了使用go-c… · 2026/9/28 2:14:08

Python整理百度云盘文件大量重复无用文件
Python整理百度云盘文件大量重复无用文件

百度云盘容量有限,当文件数量逐渐增多,空间很容易被填满。删除重复文件可以帮助释放大量空间。通过获取云盘缓存目录并使用Python脚本来整理数据,可以高效识别重复文件并避免手动操作的繁琐。 此方法基于 sqlite3 和 pandas 进行数据处理,简单快捷。 文章目录 云盘数据整理… · 2026/9/28 2:14:07

Python实现将图片转化为具有视觉震撼效果的字符图
Python实现将图片转化为具有视觉震撼效果的字符图

字符画是一种将图片转化为字符的艺术表现形式,它通过字符的密度和排列来模拟图片的色彩和形状效果。这种技术不仅在视觉上充满了创造力,还在文字处理领域展示了字符的丰富表现力。通过Python,可以将图片转换为字符画,生成具有视觉冲击力的字符艺术。 本文将通过具体步骤和… · 2026/9/28 2:13:48

Python实现将目录下的图片合并成PDF文件
Python实现将目录下的图片合并成PDF文件

在图像处理和文档管理中,经常需要将一系列图片文件合并为PDF格式,以便于传输、存档和阅读。Python凭借其丰富的第三方库,为图像处理和PDF操作提供了便捷的解决方案。 本文将详细介绍如何通过Python脚本,将目录中的所有图片合并为一个PDF文件,内容包括从基础环境配置到代码… · 2026/9/28 2:13:48

Python实现文件移动到指定文件夹
Python实现文件移动到指定文件夹

在编程过程中,经常需要对文件进行整理和管理,将不同类型的文件分类存放在指定文件夹中。Python提供了强大的文件操作模块,使得文件的移动操作变得简单高效。这篇教程将详细讲解如何使用Python实现将文件移动到指定文件夹的功能,帮助理解并掌握文件操作的基本方法和常见应用… · 2026/9/28 2:13:47

【PyQt】PyQT6制作一个Django项目启动器
【PyQt】PyQT6制作一个Django项目启动器

在现代的桌面和Web应用开发中,Python以其简单高效的特点获得了广泛的应用。通过集成PyQt和Django框架,将桌面应用的便捷操作与Django项目的后端处理相结合,不仅能够提升用户体验,更能显著提高开发的便利性和效率。 本文将聚焦于如何构建一个基于PyQt的Django项目启动器,实… · 2026/9/28 2:13:40

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

制作网页比较方便的软件怎么选?一文搞懂避坑指南
制作网页比较方便的软件怎么选?一文搞懂避坑指南

制作网页比较方便的软件怎么选?一文搞懂避坑指南 很多老板一上来就问:做个网站多少钱?但我反问他:你的域名买了吗?服务器租了吗?他一脸懵。这就是典型的“域名服务器搞不懂”。别急,今天咱们不聊虚的,直接 一文搞懂 那些让你头秃的技术名词。… · 2026/9/28 0:00:06

婚恋网站实战案例:避开3个高价坑,省钱50%还能跑赢流量
婚恋网站实战案例:避开3个高价坑,省钱50%还能跑赢流量

婚恋网站实战案例:避开3个高价坑,省钱50%还能跑赢流量 找婚恋网站建站公司,最怕的就是被坑高价。很多同行跟我吐槽,报价单上写得模棱两可,功能栏里全是“高级定制”、“专属UI”,结果落地全是套壳。今天不聊虚的,直接甩几个我经手的 实战案例… · 2026/9/28 0:00:19

济南做网站多少钱:3个案例拆解,防黑源码下载全攻略
济南做网站多少钱:3个案例拆解,防黑源码下载全攻略

济南做网站多少钱:3个案例拆解,防黑源码下载全攻略 上周济南一个做建材的老板找我,脸都绿了。他的官网首页弹出了赌博广告,后台被植入了挖矿脚本。他慌得问我:“网站被黑挂马不知道怎么办?能不能直接找之前的外包公司要源码下载,看看哪里被动了手脚?… · 2026/9/28 0:00:25

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码