如何用C#编写Windows Service监控并记录所有CMD运行信息?
实时监控CMD进程的C# Windows Service实现方案
核心思路
定时轮询进程列表的方式无法捕捉快速启动又关闭的CMD进程,必须采用实时事件监听方案。推荐使用Windows Management Instrumentation (WMI)实现,它在C#中集成简单,适合Windows Service场景,能精准捕获所有CMD进程的启动事件。
实现步骤
1. 创建Windows Service项目
在Visual Studio中新建Windows Service项目,命名为CmdMonitorService。
2. 编写监控逻辑
在服务的OnStart方法中初始化WMI事件监听,过滤并记录cmd.exe的启动信息:
using System; using System.ServiceProcess; using System.Management; using System.Diagnostics; using System.IO; namespace CmdMonitorService { public partial class CmdMonitor : ServiceBase { private ManagementEventWatcher _processWatcher; private readonly string _logPath = @"C:\CmdMonitorLogs\cmd_activity.log"; public CmdMonitor() { InitializeComponent(); Directory.CreateDirectory(Path.GetDirectoryName(_logPath)); } protected override void OnStart(string[] args) { // 监听Win32_ProcessStartTrace事件,过滤cmd.exe var query = new WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace WHERE ProcessName = 'cmd.exe'"); _processWatcher = new ManagementEventWatcher(query); _processWatcher.EventArrived += OnCmdProcessStarted; _processWatcher.Start(); } private void OnCmdProcessStarted(object sender, EventArrivedEventArgs e) { try { int pid = Convert.ToInt32(e.NewEvent.Properties["ProcessID"].Value); DateTime startTime = DateTime.Now; string commandLine = GetProcessCommandLine(pid); // 写入日志 string logEntry = $"[{startTime:yyyy-MM-dd HH:mm:ss}] PID: {pid}, Command: {commandLine}"; File.AppendAllText(_logPath, logEntry + Environment.NewLine); } catch (Exception ex) { File.AppendAllText(_logPath, $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] Error: {ex.Message}" + Environment.NewLine); } } // 获取进程命令行参数 private string GetProcessCommandLine(int pid) { using (var searcher = new ManagementObjectSearcher($"SELECT CommandLine FROM Win32_Process WHERE ProcessId = {pid}")) { foreach (ManagementObject obj in searcher.Get()) { return obj["CommandLine"]?.ToString() ?? "N/A"; } } return "N/A"; } protected override void OnStop() { _processWatcher?.Stop(); _processWatcher?.Dispose(); } } }
3. 部署服务
- 为项目添加安装程序,设置服务启动类型为
Automatic。 - 使用
InstallUtil.exe工具或Visual Studio发布功能完成服务安装,确保服务以管理员权限运行(否则无法获取进程命令行信息)。
关键说明
- WMI监听是实时触发的,不会错过短暂运行的CMD进程。
- 日志路径可自行修改,建议存储到非系统盘避免权限冲突。
- 若追求更高性能,可改用ETW(Event Tracing for Windows)的
Microsoft-Windows-Kernel-Process提供者监听ProcessStart事件,但代码复杂度更高。
原代码的局限
原代码通过Process.GetProcesses()只能获取当前存活的进程,对于快速启动又关闭的CMD进程完全无法捕捉,实时事件监听是覆盖这类场景的唯一可行方案。
内容的提问来源于stack exchange,提问作者Christopher Peterson
相关产品推荐
相关产品推荐

