You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 14:37:08