使用C# WMI类远程管理与控制Windows服务

今天早睡
今天早睡
发布时间:2026-10-13 | 4人浏览过
原创

在C#开发中,除了基础的 System.ServiceProcess 类库,System.Management 命名空间提供了更强大的 WMI(Windows Management Instrumentation)访问能力。本文将演示如何通过构造 Win32ServiceManager 类,实现对本地或远程 Windows 计算机上服务的精细控制,包括状态监控、启停管理及跨网络权限验证。

核心原理与准备条件

WMI(Windows管理规范)基于公共信息模型(CIM),为系统管理提供了一个统一的面向对象架构。在 .NET 中,System.Management 组件允许我们通过标准路径访问如 \\root\cimv2:Win32_Service 这样的命名空间对象。相较于 ServiceController,WMI 方案的优势在于能够获取更详尽的服务属性(如描述、启动模式等),并轻松支持带凭据的远程连接。

要运行以下示例代码,需要满足以下条件:

  • 项目引用:必须在项目中添加对 System.Management.dll 的引用(.NET Framework 通常内置,.NET Core/5+ 需引入 NuGet 包 System.Management)。
  • 权限配置:若操作远程计算机,目标机器必须开启 WMI 远程访问权限,且当前用户需在防火墙中允许 “Windows Management Management Instrumentation (DCOM-In)” 流量。

实现步骤:构建服务管理器类

第1步:定义管理类与初始化连接

我们创建一个名为 Win32ServiceManager 的类。该类封装了连接选项的建立过程。对于本地服务,直接连接默认命名空间;对于远程服务,需配置 ConnectionOptions 传入用户名和密码。

using System;
using System.Management;

namespace ZZ.Wmi
{
    public class Win32ServiceManager
    {
        private string strPath;
        private ManagementClass managementClass;

        // 默认构造函数:指向本地计算机
        public Win32ServiceManager() : this(".", null, null)
        {
        }

        // 带参数的构造函数:处理远程连接
        public Win32ServiceManager(string host, string userName, string password)
        {
            // 设置WMI对象路径
            this.strPath = "\\\\" + host + "\\root\\cimv2:Win32_Service";
            this.managementClass = new ManagementClass(strPath);

            if (userName != null && userName.Length > 0)
            {
                ConnectionOptions connectionOptions = new ConnectionOptions();
                connectionOptions.Username = userName;
                connectionOptions.Password = password;
                
                ManagementScope managementScope = new ManagementScope(
                    "\\\\" + host + "\\root\\cimv2", connectionOptions);
                
                this.managementClass.Scope = managementScope;
            }
        }
    }
}

第2步:实现远程连接验证方法

在进行具体操作前,建议先测试网络连接是否成功。我们可以编写一个静态辅助方法来验证远程主机可达性及认证有效性。

public static bool RemoteConnectValidate(string host, string userName, string password)
{
    ConnectionOptions connectionOptions = new ConnectionOptions();
    connectionOptions.Username = userName;
    connectionOptions.Password = password;
    
    ManagementScope managementScope = new ManagementScope(
        "\\\\" + host + "\\root\\cimv2", connectionOptions);
    
    try
    {
        managementScope.Connect();
    }
    catch
    {
        return false; // 连接失败捕获异常
    }
    
    return managementScope.IsConnected;
}

第3步:获取服务信息与列表数据

为了在前端展示或日志记录中查看服务详情,我们需要获取服务的名称、显示名称、当前状态及启动模式。此处返回二维字符串数组以便绑定到表格控件。

// 获取所有服务列表
public string[,] GetServiceList()
{
    var services = new string[this.managementClass.GetInstances().Count, 4];
    int i = 0;
    foreach (ManagementObject mo in this.managementClass.GetInstances())
    {
        services[i, 0] = (string)mo["Name"];           // 服务名
        services[i, 1] = (string)mo["DisplayName"];   // 显示名
        services[i, 2] = (string)mo["State"];         // 当前状态
        services[i, 3] = (string)mo["StartMode"];     // 启动类型
        i++;
    }
    return services;
}

// 获取指定单服务的特定属性值
public object GetServiceValue(string serviceName, string propertyName)
{
    ManagementObject mo = this.managementClass.CreateInstance();
    mo.Path = new ManagementPath(this.strPath + ".Name=\"" + serviceName + "\"");
    return mo[propertyName];
}

第4步:执行服务生命周期控制操作

利用 WMI 的 InvokeMethod 可以调用服务对象的原生动作。注意不同状态下的可执行动作约束(例如,只有“已停止”的服务才能启动,“运行中”的服务才能暂停)。

// 启动服务
public string StartService(string serviceName)
{
    string strRst = null;
    ManagementObject mo = this.managementClass.CreateInstance();
    mo.Path = new ManagementPath(this.strPath + ".Name=\"" + serviceName + "\"");
    
    try
    {
        // 检查服务状态是否为 Stopped
        if ((string)mo["State"] == "Stopped")
        {
            mo.InvokeMethod("StartService", null);
        }
    }
    catch (ManagementException e)
    {
        strRst = e.Message;
    }
    return strRst;
}

// 停止服务
public string StopService(string serviceName)
{
    string strRst = null;
    ManagementObject mo = this.managementClass.CreateInstance();
    mo.Path = new ManagementPath(this.strPath + ".Name=\"" + serviceName + "\"");
    
    try
    {
        // 检查是否接受停止请求
        if ((bool)mo["AcceptStop"])
        {
            mo.InvokeMethod("StopService", null);
        }
    }
    catch (ManagementException e)
    {
        strRst = e.Message;
    }
    return strRst;
}

// 暂停服务
public string PauseService(string serviceName)
{
    string strRst = null;
    ManagementObject mo = this.managementClass.CreateInstance();
    mo.Path = new ManagementPath(this.strPath + ".Name=\"" + serviceName + "\"");
    
    try
    {
        // 检查是否支持暂停且当前正在运行
        if ((bool)mo["AcceptPause"] && (string)mo["State"] == "Running")
        {
            mo.InvokeMethod("PauseService", null);
        }
    }
    catch (ManagementException e)
    {
        strRst = e.Message;
    }
    return strRst;
}

// 恢复暂停的服务
public string ResumeService(string serviceName)
{
    string strRst = null;
    ManagementObject mo = this.managementClass.CreateInstance();
    mo.Path = new ManagementPath(this.strPath + ".Name=\"" + serviceName + "\"");
    
    try
    {
        // 检查是否支持暂停且当前处于暂停状态
        if ((bool)mo["AcceptPause"] && (string)mo["State"] == "Paused")
        {
            mo.InvokeMethod("ResumeService", null);
        }
    }
    catch (ManagementException e)
    {
        strRst = e.Message;
    }
    return strRst;
}

完成判断与集成示例

在实际 Windows Form 应用中集成上述逻辑时,关键流程如下:

  1. 实例化:根据用户输入的主机名,判断是连接本地还是远程,进而选择相应的构造函数。
  2. 刷新列表:调用 GetServiceList() 获取数据,清空 ListView 后逐项添加 Item。
  3. 执行动作:监听按钮事件,将选中的服务名传递给对应的 StartService / StopService 等方法。
// UI层调用示例片段
private void buttonLoadRefresh_Click(object sender, EventArgs e)
{
    string host = textBoxHost.Text.Trim();
    if (string.IsNullOrEmpty(host))
    {
        MessageBox.Show("请输入计算机名或IP地址");
        return;
    }

    // 若为非本地,先验证连接
    if (host != ".")
    {
        if (!Win32ServiceManager.RemoteConnectValidate(
            host, textBoxName.Text, textBoxPassword.Text))
        {
            MessageBox.Show("连接到远程计算机验证错误.");
            return;
        }
    }

    // 创建管理器并加载数据
    this.serviceManager = new Win32ServiceManager(host, ...); // 省略密码参数细节
    string[,] services = serviceManager.GetServiceList();

    listViewService.BeginUpdate();
    listViewService.Items.Clear();
    for (int i = 0; i < services.GetLength(0); i++)
    {
        ListViewItem item = new ListViewItem(new string[] { 
            services[i, 0], services[i, 1], services[i, 2], services[i, 3] });
        listViewService.Items.Add(item);
    }
    listViewService.EndUpdate();
}

通过以上代码,你已经掌握了利用 C# 和 WMI 技术栈操控 Windows 服务的完整闭环。此方法不仅适用于简单的服务启停,还可扩展用于监控系统资源、硬件状态及其他深层 OS 指标。以上就是使用C# WMI类远程管理与控制Windows服务的详细内容,更多关于C#系统编程的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表