You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何实现Windows后台托盘程序持续检测指定进程启停并执行操作?

实现Windows托盘式进程监控后台程序

我来给你梳理一个完整的实现方案,用C# WinForms为例(这是做Windows托盘程序最顺手的方式),完全匹配你的需求:随系统启动、后台托盘运行、持续检测指定进程,进程启动后等待其关闭再执行后续操作,循环往复。

一、先搭好托盘程序的基础架子

首先创建一个WinForms项目,把主窗口隐藏,添加NotifyIcon控件来实现托盘功能:

using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;

namespace ProcessMonitorTray
{
    public partial class MainForm : Form
    {
        // 要监控的进程名(比如VLC的进程名是vlc,不用带.exe后缀)
        private readonly string _targetProcessName = "vlc";
        // 检测间隔(毫秒),别设太小,不然CPU会跑满
        private readonly int _checkInterval = 2000;
        // 后台监控线程
        private Thread _monitorThread;
        // 控制线程运行的标记
        private bool _isRunning = true;

        public MainForm()
        {
            InitializeComponent();
            // 初始化托盘图标和右键菜单
            SetupNotifyIcon();
            // 启动进程监控逻辑
            StartProcessMonitoring();
            // 程序启动后直接隐藏主窗口
            this.Hide();
        }

        private void SetupNotifyIcon()
        {
            // 替换成你自己的程序图标
            notifyIcon1.Icon = Properties.Resources.AppIcon;
            notifyIcon1.Text = "进程监控工具";
            // 给托盘加个右键退出菜单
            var contextMenu = new ContextMenuStrip();
            contextMenu.Items.Add("退出", null, ExitApp_Click);
            notifyIcon1.ContextMenuStrip = contextMenu;
            notifyIcon1.Visible = true;
        }

        private void ExitApp_Click(object sender, EventArgs e)
        {
            // 停止监控线程
            _isRunning = false;
            _monitorThread.Join();
            // 隐藏托盘图标并退出程序
            notifyIcon1.Visible = false;
            Application.Exit();
        }
    }
}

二、核心的进程监控逻辑

接下来实现最关键的「持续检测+等待进程退出+后续操作」逻辑,把它放到StartProcessMonitoring方法里:

private void StartProcessMonitoring()
{
    _monitorThread = new Thread(() =>
    {
        while (_isRunning)
        {
            // 查找目标进程
            var targetProcesses = Process.GetProcessesByName(_targetProcessName);
            if (targetProcesses.Length > 0)
            {
                Debug.WriteLine($"检测到{_targetProcessName}启动,等待它关闭...");
                // 这里取第一个进程实例,如果要处理多实例可以遍历数组
                var targetProc = targetProcesses[0];
                try
                {
                    // 阻塞线程,直到进程关闭
                    targetProc.WaitForExit();
                    // 进程关闭后执行你需要的后续操作
                    RunPostExitActions();
                }
                catch (InvalidOperationException ex)
                {
                    // 处理极端情况:刚检测到进程,还没等WaitForExit就已经关闭了
                    Debug.WriteLine($"处理进程时出错:{ex.Message}");
                }
            }
            // 间隔一段时间再检测,避免CPU占用过高
            Thread.Sleep(_checkInterval);
        }
    });
    // 设置为后台线程,程序退出时会自动终止
    _monitorThread.IsBackground = true;
    _monitorThread.Start();
}

private void RunPostExitActions()
{
    // 这里写你要执行的后续操作,比如记录日志、启动其他程序等
    Debug.WriteLine($"{_targetProcessName}已关闭,执行后续操作...");
    // 示例:给用户弹个托盘提示(注意跨线程操作UI必须用Invoke)
    this.Invoke((MethodInvoker)delegate
    {
        notifyIcon1.ShowBalloonTip(3000, "提示", $"{_targetProcessName}已经关闭", ToolTipIcon.Info);
    });
}

三、设置随Windows启动

有两种简单的方式实现开机自启:

  1. 写入当前用户注册表:不需要管理员权限,只对当前用户生效
    // 可以放到MainForm构造函数里执行
    using Microsoft.Win32;
    private void SetAutoStartup()
    {
        var appPath = Application.ExecutablePath;
        var registryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
        // 键名可以自定义,值是你的程序完整路径
        registryKey.SetValue("ProcessMonitorTray", appPath);
    }
    
  2. 创建快捷方式到启动文件夹:找到路径C:\Users\[你的用户名]\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup,把程序的快捷方式放进去就行。

几个关键注意点要记牢

  • CPU占用控制:一定要加Thread.Sleep(_checkInterval),建议间隔1-5秒,根据你的需求调整,别让循环跑太快。
  • 跨线程操作UI:如果在监控线程里要操作UI(比如托盘提示),必须用Invoke/BeginInvoke,不然会抛出跨线程异常。
  • 多实例处理:如果目标程序可能开多个窗口,你可以遍历targetProcesses数组,等待所有实例退出,或者按需处理单个实例。
  • 异常防护:加try-catch块处理进程突然关闭、权限不足等异常,避免监控线程崩溃。

如果你习惯用Python,也可以用psutil库检测进程,pystray库做托盘,核心逻辑是完全一致的:循环检测→发现进程→等待退出→执行操作→回到循环。比如核心代码片段:

import psutil
import time

def monitor_target_process(target_name):
    while True:
        # 遍历所有进程查找目标
        for proc in psutil.process_iter(['name']):
            if proc.info['name'].lower() == target_name.lower():
                print(f"检测到{target_name}启动,等待退出...")
                proc.wait()
                print(f"{target_name}已关闭,执行后续操作")
                # 这里写你的后续操作代码
                break
        # 间隔2秒再检测
        time.sleep(2)

这样整个流程就完全闭环了:程序启动后最小化到托盘,一直监控目标进程,进程启动后就等着它关闭,执行完后续操作又回到检测状态,直到用户右键托盘退出程序。

内容的提问来源于stack exchange,提问作者shook_one

火山引擎 最新活动