• C# 守护进程的介绍及实现


    1、为什么需要守护进程

    一般是为了保护我们的程序/服务的正常运行,当程序被关闭、异常退出等时再次启动程序/恢复服务

    2、守护进程有哪几种方式

    常见的守护进程的方式:
    1、轮询(轮询最简单也最low,这里不再作说明)
    2、监听系统事件
    3、WMI查询事件

    3、监听系统事件 和 WMI查询事件代码实现

    1) 系统事件监听进程的关闭

    需要引入 System.Diagnostics namespace
    原理便是通过订阅 Exited 事件
    优点:代码简洁,逻辑清晰
    缺点:无法监听进程的启动,且只能监听进程的正常退出,异常导致程序崩溃监听不到。

    代码实现:

    using System.Diagnostics;
    
    var p = Process.GetProcessesByName("notepad")[0];
    p.EnableRaisingEvents = true;
    p.Exited += P_Exited;
    
    Console.ReadLine();
    
    void P_Exited(object? sender, EventArgs e)
    {
        p = Process.Start("notepad");
    
        p.EnableRaisingEvents = true;
        p.Exited += P_Exited;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2)WMI监听进程的启动和关闭

    WMI简介
    Windows Management Instrumentation(WMI)是用于管理基于 Windows 操作系统的数据和操作的基础结构。

    WMIC
    是WMI的命令行管理工具。
    使用 WMIC,不但可以管理本地计算机,而且还可以管理同一Windows域内的所有远程计算机(需要必要的权限),而被管理的远程计算机不必是先安装WMIC,只需要支持WMI即可。WMIC有一个能搞分析、解释和执行从命令行接受的别名(Alias)的引擎,他是一个可执行文件,名为 WMIC.exe,这个文件通常位于 “C:\Windows\System32\wbem” 文件夹中(支持Windows XP和Windows2003及以后的系统)

    命令行例子:wmic cpu get name 查看CPU信息

    有需要深入研究的小伙伴可以去看看:WMI编程手册

    代码实现:

    说明:System.Management namespace
    .net framework版本中默认存在,直接引入即可
    .net core中需要NuGet安装 “System.Management” 包

    using System.Management;
    
    // 查询进程创建 1秒钟通知
    var qCreate = new WqlEventQuery($"__InstanceCreationEvent", TimeSpan.FromSeconds(1), $"TargetInstance isa \"Win32_Process\" and TargetInstance.Name = 'Notepad.exe'");
    
    // 查询进程关闭 1秒钟通知
    var qDelete = new WqlEventQuery($"__InstanceDeletionEvent", TimeSpan.FromSeconds(1), $"TargetInstance isa \"Win32_Process\" and TargetInstance.Name = 'Notepad.exe'");
    
    // 创建事件查询的监听器
    ManagementEventWatcher wCreate = new ManagementEventWatcher(qCreate);
    ManagementEventWatcher wDelete = new ManagementEventWatcher(qDelete);
    
    // 注册事件
    wCreate.EventArrived += (sender, e) =>
    {
        Console.WriteLine($"进程启动:{GetInfo(e.NewEvent)}");
    };
    
    wDelete.EventArrived += (sender, e) =>
    {
        Console.WriteLine($"进程关闭:{GetInfo(e.NewEvent)}");
    };
    
    // 开始监听
    wCreate.Start();
    wDelete.Start();
    Console.ReadLine();
    
    static string GetInfo(ManagementBaseObject obj)
    {
        var instance = obj["TargetInstance"] as ManagementBaseObject;
        return $"{instance["Name"]}-{instance["ProcessId"]}";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    为了简明思路代码中并没有是现在进程退出后重新启动,有需要可以使用前面的 Process.Start("notepad"); 实现重启

  • 相关阅读:
    学习-Java输入输出之字符缓冲IO流之往文件中插入分隔符
    图论第9天
    Unity性能优化笔记——UI优化
    opencv 任意两点切割图像
    选择排序、冒泡排序、快速排序、归并排序
    多机分布式执行异步任务的实现姿势
    谷粒商城-基础篇-Day02
    C++深度解析教程 - 目录
    string
    持续集成(CICD)- gogs仓库的部署和使用
  • 原文地址:https://blog.csdn.net/qq_43562262/article/details/125448560