.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




