2025-10-31
C#
00

目录

🎯 为什么需要自建监控工具?
现有工具的痛点
自建工具的优势
🏗️ 整体架构设计
💻 核心功能实现
🚀 1. WMI系统信息获取
🎯 2. 实时进程监控
🎨 3. 现代化UI设计
📊 4. 内存和磁盘监控
⚡ 性能优化技巧
1. 异步处理策略
2. 内存管理
3. 定时器优化
🔥 实战应用场景
1. 服务监控
2. 资源预警
🎯 常见问题与解决方案
Q: WMI查询权限不足怎么办?
Q: 如何提高查询性能?
Q: 界面卡顿怎么解决?
🚀 扩展功能建议
📝 总结

你是否曾经因为找不到占用大量资源的进程而苦恼?或者想要实时监控某个重要服务的运行状态?作为C#开发者,我们完全可以自己动手打造一个功能强大的系统监控工具。今天就带你一步步构建一个基于WPF和WMI的专业级系统监控应用,让你的程序拥有"透视"整个系统的能力!

这不仅仅是一个简单的Demo,而是一个可以直接投入生产使用的完整解决方案。从界面设计到核心功能,从性能优化到异常处理,我们都会详细讲解。

🎯 为什么需要自建监控工具?

现有工具的痛点

  • 任务管理器:功能单一,无法自定义监控逻辑
  • 第三方工具:收费昂贵,或者功能过于复杂
  • 系统自带工具:界面老旧,不够直观

自建工具的优势

  • 完全可控:根据业务需求定制功能
  • 深度集成:与现有系统完美结合
  • 学习价值:深入理解系统底层机制

🏗️ 整体架构设计

我们的监控工具采用MVVM模式,主要包含以下核心模块:

Markdown
📦 AppWmiSystemMonitor ├── 🎨 UI层 (WPF界面) ├── 🧠 业务逻辑层 (进程监控、数据处理) ├── 🔌 数据访问层 (WMI接口) └── 📊 数据模型层 (实体类定义)

💻 核心功能实现

🚀 1. WMI系统信息获取

WMI(Windows Management Instrumentation)是Windows提供的强大系统管理接口,我们可以通过它获取几乎所有的系统信息:

C#
private async Task LoadSystemInfoAsync() { await Task.Run(() => { try { var items = new List<SystemInfoItem>(); // 获取计算机系统信息 using (var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_ComputerSystem")) { foreach (ManagementObject obj in searcher.Get()) { items.Add(new SystemInfoItem { Property = "计算机名", Value = obj["Name"]?.ToString() ?? "N/A" }); items.Add(new SystemInfoItem { Property = "制造商", Value = obj["Manufacturer"]?.ToString() ?? "N/A" }); items.Add(new SystemInfoItem { Property = "型号", Value = obj["Model"]?.ToString() ?? "N/A" }); } } Dispatcher.Invoke(() => { SystemInfoItems.Clear(); foreach (var item in items) { SystemInfoItems.Add(item); } }); } catch (Exception ex) { Dispatcher.Invoke(() => AddLog($"❌ 加载系统信息失败: {ex.Message}", LogLevel.Error)); } }); }

关键技术点:

  • 使用ManagementObjectSearcher执行WQL查询
  • 异步处理避免界面卡顿
  • Dispatcher.Invoke确保UI线程安全

🎯 2. 实时进程监控

这是整个工具的核心功能,通过WMI事件监控实现进程的实时跟踪:

C#
public class ProcessWatcher { private ManagementEventWatcher _startWatcher; private ManagementEventWatcher _stopWatcher; private string _processName; public ProcessWatcher(string processName, Action<ProcessEventArgs> onProcessEvent) { _processName = processName.ToLower(); ProcessEvent = onProcessEvent; InitializeWatchers(); } private void InitializeWatchers() { try { // 监控进程启动 string startQuery = "SELECT * FROM Win32_ProcessStartTrace"; _startWatcher = new ManagementEventWatcher(new WqlEventQuery(startQuery)); _startWatcher.EventArrived += OnProcessStarted; // 监控进程终止 string stopQuery = "SELECT * FROM Win32_ProcessStopTrace"; _stopWatcher = new ManagementEventWatcher(new WqlEventQuery(stopQuery)); _stopWatcher.EventArrived += OnProcessStopped; } catch (Exception ex) { throw new Exception($"初始化进程监控器失败: {ex.Message}", ex); } } private void OnProcessStarted(object sender, EventArrivedEventArgs e) { try { string processName = e.NewEvent.Properties["ProcessName"]?.Value?.ToString()?.ToLower(); if (!string.IsNullOrEmpty(processName) && processName == _processName) { uint processId = (uint)e.NewEvent.Properties["ProcessID"].Value; ProcessEvent?.Invoke(new ProcessEventArgs { ProcessName = processName, ProcessId = processId, EventType = ProcessEventType.Started, Timestamp = DateTime.Now }); } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"处理进程启动事件时出错: {ex.Message}"); } } }

实战技巧:

  • 使用事件驱动模式,避免轮询造成的性能损耗
  • 合理的异常处理,确保监控器稳定运行
  • 支持自定义回调,便于业务逻辑集成

🎨 3. 现代化UI设计

一个好的工具离不开优秀的用户界面。我们采用现代化的设计风格:

XML
<Style x:Key="EasyButton" TargetType="Button"> <Setter Property="Background" Value="#017a7a"/> <Setter Property="Foreground" Value="White"/> <Setter Property="BorderThickness" Value="0"/> <Setter Property="Margin" Value="10"/> <Setter Property="Padding" Value="20,12" /> <Setter Property="FontSize" Value="15"/> <Setter Property="FontWeight" Value="SemiBold"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Border Background="{TemplateBinding Background}" CornerRadius="1"> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/> </Border> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Background" Value="#005CBF"/> </Trigger> <Trigger Property="IsPressed" Value="True"> <Setter Property="Background" Value="#004A99"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>

设计亮点:

  • 统一的视觉风格,提升用户体验
  • 响应式交互效果,增强操作反馈
  • 可复用的样式资源,便于维护升级

📊 4. 内存和磁盘监控

实时监控系统资源使用情况:

C#
private async Task LoadMemoryInfoAsync() { await Task.Run(() => { try { var items = new List<MemoryInfoItem>(); using (var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem")) { foreach (ManagementObject obj in searcher.Get()) { ulong totalMemory = Convert.ToUInt64(obj["TotalVisibleMemorySize"]) * 1024; ulong freeMemory = Convert.ToUInt64(obj["FreePhysicalMemory"]) * 1024; ulong usedMemory = totalMemory - freeMemory; double usagePercent = (double)usedMemory / totalMemory * 100; items.Add(new MemoryInfoItem { Property = "总物理内存", Value = FormatBytes(totalMemory) }); items.Add(new MemoryInfoItem { Property = "已使用内存", Value = FormatBytes(usedMemory) }); items.Add(new MemoryInfoItem { Property = "内存使用率", Value = $"{usagePercent:F1}%" }); } } Dispatcher.Invoke(() => { MemoryInfoItems.Clear(); foreach (var item in items) { MemoryInfoItems.Add(item); } }); } catch (Exception ex) { Dispatcher.Invoke(() => AddLog($"❌ 加载内存信息失败: {ex.Message}", LogLevel.Error)); } }); } private static string FormatBytes(ulong bytes, bool showMB = true) { if (bytes == 0) return "0 B"; string[] sizes = { "B", "KB", "MB", "GB", "TB" }; int order = 0; double size = bytes; while (size >= 1024 && order < sizes.Length - 1) { order++; size /= 1024; } return $"{size:F1} {sizes[order]}"; }

image.png

image.png

⚡ 性能优化技巧

1. 异步处理策略

C#
// ✅ 推荐:异步加载,避免界面卡顿 private async void RefreshSystemButton_Click(object sender, RoutedEventArgs e) { await LoadSystemInfoAsync(); AddLog("🔄 系统信息已刷新", LogLevel.Info); } // ❌ 避免:同步调用导致界面假死 private void RefreshSystemButton_Click_Bad(object sender, RoutedEventArgs e) { LoadSystemInfo(); // 这会阻塞UI线程 }

2. 内存管理

C#
protected override void OnClosed(EventArgs e) { // 及时释放资源,避免内存泄漏 _processWatcher?.StopMonitoring(); _systemInfoTimer?.Stop(); base.OnClosed(e); }

3. 定时器优化

C#
private void InitializeTimer() { _systemInfoTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(5) // 合理的刷新频率 }; _systemInfoTimer.Tick += SystemInfoTimer_Tick; }

🔥 实战应用场景

1. 服务监控

C#
// 监控关键服务进程 private void HandleProcessClosed(uint processId, string processName) { if (processName.ToLower().Contains("service") || processName.ToLower().Contains("server")) { AddLog($"⚠️ 检测到服务进程 {processName} 意外终止,可能需要人工干预", LogLevel.Warning); // 这里可以添加自动重启逻辑 RestartService(processName); } }

2. 资源预警

C#
private void CheckResourceUsage() { if (usagePercent > 90) { AddLog($"🚨 内存使用率过高: {usagePercent:F1}%", LogLevel.Warning); // 发送预警通知 SendAlert($"系统内存使用率达到{usagePercent:F1}%"); } }

🎯 常见问题与解决方案

Q: WMI查询权限不足怎么办?

A: 确保程序以管理员权限运行,或者在代码中添加权限检查:

C#
var options = new ConnectionOptions(); options.Impersonation = ImpersonationLevel.Impersonate; options.EnablePrivileges = true;

Q: 如何提高查询性能?

A: 使用精确的WQL查询条件,避免SELECT *:

C#
// ✅ 推荐:指定具体字段 "SELECT Name, ProcessID, WorkingSetSize FROM Win32_Process WHERE Name='notepad.exe'" // ❌ 避免:查询所有字段 "SELECT * FROM Win32_Process"

Q: 界面卡顿怎么解决?

A: 所有耗时操作都要异步处理,并合理控制更新频率。

🚀 扩展功能建议

  1. 网络监控:添加网络流量统计功能
  2. 性能图表:集成图表库显示历史数据
  3. 告警系统:支持邮件、短信等多种告警方式
  4. 配置管理:支持监控规则的动态配置
  5. 日志导出:支持将监控数据导出为Excel或CSV

📝 总结

通过本文,我们完整实现了一个功能丰富的WPF系统监控工具。核心要点包括:

  1. WMI技术:掌握了Windows系统信息查询的标准方法
  2. 异步编程:学会了如何在WPF中正确使用异步操作保证界面响应
  3. 事件驱动:理解了如何使用WMI事件实现高效的进程监控

这个项目不仅展示了C#的强大功能,更体现了.NET平台在系统编程方面的优势。你可以基于这个框架继续扩展,打造属于自己的专业级监控工具!

你在开发监控工具时遇到过哪些挑战?或者有什么创新的监控需求?欢迎在评论区分享你的经验和想法!如果觉得这篇文章对你有帮助,别忘了转发给更多同行朋友! 🎉

相关信息

通过网盘分享的文件:AppWmiSystemMonitor.zip 链接: https://pan.baidu.com/s/1Jittec8C5KZiK3f3JiKiOw?pwd=j1zw 提取码: j1zw --来自百度网盘超级会员v9的分享

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!