【问题标题】:How to monitor windows services using c#如何使用c#监控windows服务
【发布时间】:2016-04-19 07:03:10
【问题描述】:

如何使用 c# 监控 Windows 服务,并且我还必须将这些服务名称、开始时间和服务结束时间保存在 CSV 文件中。如果有任何新服务启动,它应该使用现有的 CSV 文件自动写入服务名称、启动时间和服务结束时间。

【问题讨论】:

  • Windows 已经在事件日志中记录了这些信息。为什么不直接使用它?
  • 我可以从哪里得到这个日志文件@Damien_The_Unbeliever

标签: c# windows service


【解决方案1】:

如果有人在 2021 年寻找解决方案,您可以使用服务控制器、异步任务和 WaitForStatus() 方法来做到这一点:

更新:我意识到我最初的解决方案行不通,所以我完全重写了它:

类定义

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.ServiceProcess; // not referenced by default

public class ExtendedServiceController: ServiceController
{
    public event EventHandler<ServiceStatusEventArgs> StatusChanged;
    private Dictionary<ServiceControllerStatus, Task> _tasks = new Dictionary<ServiceControllerStatus, Task>();

    new public ServiceControllerStatus Status
    {
        get
        {
            base.Refresh();
            return base.Status;
        }
    }

    public ExtendedServiceController(string ServiceName): base(ServiceName)
    {
        foreach (ServiceControllerStatus status in Enum.GetValues(typeof(ServiceControllerStatus)))
        {
            _tasks.Add(status, null);
        }
        StartListening();
    }

    private void StartListening()
    {
        foreach (ServiceControllerStatus status in Enum.GetValues(typeof(ServiceControllerStatus)))
        {
            if (this.Status != status && (_tasks[status] == null || _tasks[status].IsCompleted))
            {
                _tasks[status] = Task.Run(() =>
                {
                    try
                    {
                        base.WaitForStatus(status);
                        OnStatusChanged(new ServiceStatusEventArgs(status));
                        StartListening();
                    }
                    catch
                    {
                        // You can either raise another event here with the exception or ignore it since it most likely means the service was uninstalled/lost communication
                    }
                });
            }
        }
    }

    protected virtual void OnStatusChanged(ServiceStatusEventArgs e)
    {
        EventHandler<ServiceStatusEventArgs> handler = StatusChanged;
        handler?.Invoke(this, e);
    }
}

public class ServiceStatusEventArgs : EventArgs
{
    public ServiceControllerStatus Status { get; private set; }
    public ServiceStatusEventArgs(ServiceControllerStatus Status)
    {
        this.Status = Status;
    }
}

用法

static void Main(string[] args)
{
    ExtendedServiceController xServiceController = new ExtendedServiceController("myService");
    xServiceController.StatusChanged += xServiceController_StatusChanged;
    Console.Read();

    // Added bonus since the class inherits from ServiceController, you can use it to control the service as well.
}

// This event handler will catch service status changes externally as well
private static void xServiceController_StatusChanged(object sender, ServiceStatusEventArgs e)
{
    Console.WriteLine("Status Changed: " + e.Status);
}

【讨论】:

  • 您可能希望使用WaitForStatus(ServiceControllerStatus, TimeSpan) 指定超时并在服务未在合理的时间内达到运行状态时做出相应的反应。
  • Eric:我意识到我最初的解决方案行不通,所以我完全重写了它,并提出了一个 ServiceController 扩展器来监控服务并引发事件。可能需要更多测试,但可以按预期工作。
【解决方案2】:

您可以使用ServiceControllerManagementObjectSearcher 列出正在运行的服务。

这是使用ManagementObjectSearcher 的示例:

using System.Management;

...

StringBuilder sb = new StringBuilder();
string format = "{0},{1},{2},{3},{4}";

// Header line
sb.AppendFormat(format, "DisplayName", 
                        "ServiceName", 
                        "Status", 
                        "ProcessId", 
                        "PathName");
sb.AppendLine();

ManagementObjectSearcher searcher = 
           new ManagementObjectSearcher("SELECT * FROM Win32_Service");

foreach( ManagementObject result in searcher.Get() )
{
    sb.AppendFormat(format, result["DisplayName"], 
                            result["Name"], 
                            result["State"], 
                            result["ProcessId"], 
                            result["PathName"]
                   );
    sb.AppendLine();
}

File.WriteAllText(
         @"C:\temp\ManagementObjectSearcher_services.csv", 
         sb.ToString()
);

要获取开始和停止时间,您似乎必须查询 Windows 事件日志。

这篇博文展示了如何监控事件日志以在服务停止或启动时获得通知: https://dotnetcodr.com/2014/12/02/getting-notified-by-a-windows-service-status-change-in-c-net/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-05
    • 2011-06-05
    相关资源
    最近更新 更多