你是否曾经因为找不到占用大量资源的进程而苦恼?或者想要实时监控某个重要服务的运行状态?作为C#开发者,我们完全可以自己动手打造一个功能强大的系统监控工具。今天就带你一步步构建一个基于WPF和WMI的专业级系统监控应用,让你的程序拥有"透视"整个系统的能力!
这不仅仅是一个简单的Demo,而是一个可以直接投入生产使用的完整解决方案。从界面设计到核心功能,从性能优化到异常处理,我们都会详细讲解。
我们的监控工具采用MVVM模式,主要包含以下核心模块:
Markdown📦 AppWmiSystemMonitor ├── 🎨 UI层 (WPF界面) ├── 🧠 业务逻辑层 (进程监控、数据处理) ├── 🔌 数据访问层 (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线程安全这是整个工具的核心功能,通过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}");
}
}
}
实战技巧:
一个好的工具离不开优秀的用户界面。我们采用现代化的设计风格:
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>
设计亮点:
实时监控系统资源使用情况:
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]}";
}


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线程
}
C#protected override void OnClosed(EventArgs e)
{
// 及时释放资源,避免内存泄漏
_processWatcher?.StopMonitoring();
_systemInfoTimer?.Stop();
base.OnClosed(e);
}
C#private void InitializeTimer()
{
_systemInfoTimer = new DispatcherTimer
{
Interval = TimeSpan.FromSeconds(5) // 合理的刷新频率
};
_systemInfoTimer.Tick += SystemInfoTimer_Tick;
}
C#// 监控关键服务进程
private void HandleProcessClosed(uint processId, string processName)
{
if (processName.ToLower().Contains("service") || processName.ToLower().Contains("server"))
{
AddLog($"⚠️ 检测到服务进程 {processName} 意外终止,可能需要人工干预", LogLevel.Warning);
// 这里可以添加自动重启逻辑
RestartService(processName);
}
}
C#private void CheckResourceUsage()
{
if (usagePercent > 90)
{
AddLog($"🚨 内存使用率过高: {usagePercent:F1}%", LogLevel.Warning);
// 发送预警通知
SendAlert($"系统内存使用率达到{usagePercent:F1}%");
}
}
A: 确保程序以管理员权限运行,或者在代码中添加权限检查:
C#var options = new ConnectionOptions();
options.Impersonation = ImpersonationLevel.Impersonate;
options.EnablePrivileges = true;
A: 使用精确的WQL查询条件,避免SELECT *:
C#// ✅ 推荐:指定具体字段
"SELECT Name, ProcessID, WorkingSetSize FROM Win32_Process WHERE Name='notepad.exe'"
// ❌ 避免:查询所有字段
"SELECT * FROM Win32_Process"
A: 所有耗时操作都要异步处理,并合理控制更新频率。
通过本文,我们完整实现了一个功能丰富的WPF系统监控工具。核心要点包括:
这个项目不仅展示了C#的强大功能,更体现了.NET平台在系统编程方面的优势。你可以基于这个框架继续扩展,打造属于自己的专业级监控工具!
你在开发监控工具时遇到过哪些挑战?或者有什么创新的监控需求?欢迎在评论区分享你的经验和想法!如果觉得这篇文章对你有帮助,别忘了转发给更多同行朋友! 🎉
相关信息
通过网盘分享的文件:AppWmiSystemMonitor.zip 链接: https://pan.baidu.com/s/1Jittec8C5KZiK3f3JiKiOw?pwd=j1zw 提取码: j1zw --来自百度网盘超级会员v9的分享
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!