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

.NET Core 2.0中如何检查Windows服务是否运行?

如何在.NET Core 2.0中检查Windows服务运行状态

确实,在.NET Core 2.0里微软还没把ServiceController纳入核心类库,不过有两个靠谱的方案可以实现服务状态检查,我给你详细拆解下:

方案1:使用官方兼容NuGet包

微软针对.NET Core早期版本提供了System.ServiceProcess.ServiceController的兼容NuGet包,这是最省心的方式,因为它和你熟悉的.NET Framework版本用法完全一致。

步骤1:安装NuGet包

用包管理器控制台执行:

Install-Package System.ServiceProcess.ServiceController -Version 4.6.0

或者用.NET CLI:

dotnet add package System.ServiceProcess.ServiceController --version 4.6.0

(这个版本是经过验证支持.NET Core 2.0的,更高版本也可以试试,但4.6.0是最稳定的选择之一)

步骤2:编写检查代码

安装完成后,你就可以像在.NET Framework里一样使用ServiceController了:

using System.ServiceProcess;

public class ServiceChecker
{
    public bool IsServiceRunning(string serviceName)
    {
        using (var serviceController = new ServiceController(serviceName))
        {
            try
            {
                return serviceController.Status == ServiceControllerStatus.Running;
            }
            catch (InvalidOperationException)
            {
                // 要么服务不存在,要么当前用户没有权限访问服务信息
                return false;
            }
        }
    }
}

注意事项

  • 运行程序时需要管理员权限,否则可能会抛出权限不足的异常;
  • 这个包是微软官方维护的,不用担心第三方依赖的风险。

方案2:直接调用Windows原生API(无NuGet依赖)

如果你的项目不想引入任何外部NuGet包,可以通过P/Invoke直接调用Windows的服务管理API,虽然代码稍微复杂点,但完全可控。

下面是完整的实现代码:

using System;
using System.Runtime.InteropServices;

public static class WindowsServiceHelper
{
    // 服务管理器访问权限
    private const int SC_MANAGER_CONNECT = 0x0001;
    // 服务查询权限
    private const int SERVICE_QUERY_STATUS = 0x0004;
    // 服务运行状态的标识
    private const int SERVICE_RUNNING = 0x0004;

    // 服务状态结构体,对应Windows API的定义
    [StructLayout(LayoutKind.Sequential)]
    private struct SERVICE_STATUS
    {
        public int dwServiceType;
        public int dwCurrentState;
        public int dwControlsAccepted;
        public int dwWin32ExitCode;
        public int dwServiceSpecificExitCode;
        public int dwCheckPoint;
        public int dwWaitHint;
    }

    // 打开服务管理器
    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern IntPtr OpenSCManager(string lpMachineName, string lpDatabaseName, int dwDesiredAccess);

    // 打开指定服务
    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, int dwDesiredAccess);

    // 查询服务状态
    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool QueryServiceStatus(IntPtr hService, ref SERVICE_STATUS lpServiceStatus);

    // 关闭服务句柄
    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool CloseServiceHandle(IntPtr hSCObject);

    public static bool IsServiceRunning(string serviceName)
    {
        // 打开本地服务管理器
        IntPtr scManagerHandle = OpenSCManager(null, null, SC_MANAGER_CONNECT);
        if (scManagerHandle == IntPtr.Zero)
        {
            // 无法打开服务管理器,可能是权限不足
            return false;
        }

        try
        {
            // 打开目标服务
            IntPtr serviceHandle = OpenService(scManagerHandle, serviceName, SERVICE_QUERY_STATUS);
            if (serviceHandle == IntPtr.Zero)
            {
                // 服务不存在或者无法访问
                return false;
            }

            try
            {
                SERVICE_STATUS serviceStatus = new SERVICE_STATUS();
                if (QueryServiceStatus(serviceHandle, ref serviceStatus))
                {
                    // 判断是否处于运行状态
                    return serviceStatus.dwCurrentState == SERVICE_RUNNING;
                }
                else
                {
                    // 查询状态失败
                    return false;
                }
            }
            finally
            {
                // 务必关闭服务句柄,避免资源泄漏
                CloseServiceHandle(serviceHandle);
            }
        }
        finally
        {
            // 关闭服务管理器句柄
            CloseServiceHandle(scManagerHandle);
        }
    }
}

注意事项

  • 同样需要管理员权限才能正常访问服务信息;
  • 代码中已经处理了句柄的释放,避免资源泄漏,使用时直接调用WindowsServiceHelper.IsServiceRunning("你的服务名")即可。

额外建议

如果项目允许的话,建议你考虑升级到.NET Core 3.0或更高版本——微软从.NET Core 3.0开始,已经把ServiceController原生纳入了核心类库,不需要再安装额外NuGet包,用法和.NET Framework完全一致,开发体验会更好。

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

火山引擎 最新活动