You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在.NET 4.7中创建Decoupled MI Provider?Windows NT服务场景

Hey there! Let's break this down step by step—you're dealing with a tricky mix of legacy tech and under-documented newer MI tooling, so I'll start by clearing up the terminology confusion, then walk you through creating a decoupled MI provider in .NET 4.7 for your NT services.

First: Let's Unpack Those Terms

I totally get the confusion with all the acronyms—here's a quick, plain-English breakdown:

  • WMI (v1): The old, COM-based Windows Management Instrumentation system you're finding all the outdated examples for. Microsoft has officially deprecated this, so you're right to avoid it.
  • MI (Management Infrastructure): WMI's modern replacement (often called WMIv2). It's lighter, more efficient, and built on the industry-standard CIM (Common Information Model).
  • CIM / CIMv2: CIM is a universal standard for defining management data; CIMv2 is the most widely used version (you might recognize it from the root/cimv2 namespace in old WMI). MI is Microsoft's implementation of CIM for Windows.
  • MMI (Managed Management Infrastructure): The .NET wrapper for MI, letting you write MI providers in C#/VB.NET instead of native C++.
  • Decoupled MI Provider: A type of MI provider that runs as a separate process from your NT services. This keeps your service's stability independent of the monitoring provider—if the provider crashes, your service keeps running, and vice versa.

Creating a Decoupled MI Provider in .NET 4.7

Since there's scarce documentation for this, here's a working example tailored to your use case (exposing NT service status for monitoring):

1. Set Up Your Project

  • Create a new Class Library (.NET Framework 4.7) project (or a Console App if you want to run the provider as a standalone process).
  • Install the Microsoft.Management.Infrastructure NuGet package—this gives you access to the MMI APIs.

2. Define Your CIM Data Class

First, create a .NET class that maps to the CIM object you want to expose (this is what monitoring tools will query):

using Microsoft.Management.Infrastructure;

[CimClass("MyServiceStatus", Namespace = "root/MyServiceMonitor")]
public class MyServiceStatus
{
    [CimKey] // Marks this as a unique identifier for the instance
    public string ServiceName { get; set; }

    // 0 = Stopped, 1 = Running, 2 = Paused, 3 = Other, 4 = Error
    public uint Status { get; set; }

    public DateTime LastStartTime { get; set; }

    public ulong UptimeSeconds { get; set; }
}

3. Build the Provider Host

Create a host (we'll use a console app for simplicity) that listens for MI queries and returns your service status data:

using Microsoft.Management.Infrastructure;
using Microsoft.Management.Infrastructure.Options;
using System;
using System.ServiceProcess;
using System.Threading;

namespace MyServiceMIProvider
{
    class ProviderHost
    {
        static void Main(string[] args)
        {
            // Configure the provider and target namespace
            var providerOptions = new CimProviderOptions("MyServiceMonitorProvider");
            var targetNamespace = "root/MyServiceMonitor";

            // Initialize the CIM server to handle incoming queries
            using (var cimServer = new CimServer(providerOptions))
            {
                // Register our class and request handler
                cimServer.RegisterInstanceProvider(targetNamespace, typeof(MyServiceStatus), HandleInstanceRequests);

                Console.WriteLine("Decoupled MI Provider running... Press Ctrl+C to stop.");
                var shutdownEvent = new ManualResetEvent(false);
                Console.CancelKeyPress += (sender, e) => shutdownEvent.Set();
                shutdownEvent.WaitOne();
            }
        }

        // Handles incoming queries for service status data
        static CimInstance HandleInstanceRequests(CimRequest request)
        {
            // Replace these with your actual NT service names
            var targetServices = new[] { "Service1", "Service2", "Service3" };

            foreach (var serviceName in targetServices)
            {
                using (var serviceController = new ServiceController(serviceName))
                {
                    try
                    {
                        // Map ServiceController status to our custom code
                        var statusCode = serviceController.Status switch
                        {
                            ServiceControllerStatus.Running => 1,
                            ServiceControllerStatus.Stopped => 0,
                            ServiceControllerStatus.Paused => 2,
                            _ => 3
                        };

                        // Calculate uptime if the service is running
                        var uptime = serviceController.Status == ServiceControllerStatus.Running
                            ? (ulong)(DateTime.Now - serviceController.StartTime).TotalSeconds
                            : 0;

                        // Return the populated CIM instance
                        return new CimInstance(typeof(MyServiceStatus))
                        {
                            CimInstanceProperties =
                            {
                                { "ServiceName", CimValue.Create(serviceName) },
                                { "Status", CimValue.Create(statusCode) },
                                { "LastStartTime", CimValue.Create(serviceController.StartTime) },
                                { "UptimeSeconds", CimValue.Create(uptime) }
                            }
                        };
                    }
                    catch (Exception)
                    {
                        // Return an error state if the service can't be accessed
                        return new CimInstance(typeof(MyServiceStatus))
                        {
                            CimInstanceProperties =
                            {
                                { "ServiceName", CimValue.Create(serviceName) },
                                { "Status", CimValue.Create(4) },
                                { "LastStartTime", CimValue.Create(DateTime.MinValue) },
                                { "UptimeSeconds", CimValue.Create(0UL) }
                            }
                        };
                    }
                }
            }
            return null;
        }
    }
}

4. Register the Provider

To let Windows know about your MI provider, use the miregprov.exe tool (included with the Windows SDK):

  1. Open an elevated command prompt.
  2. Run this command (replace the path with your compiled provider executable):
miregprov.exe -n root/MyServiceMonitor -p MyServiceMonitorProvider -c "C:\Path\To\Your\MyServiceMIProvider.exe"

5. Test the Provider

You can verify it works using tools like:

  • Get-CimInstance in PowerShell:
    Get-CimInstance -Namespace root/MyServiceMonitor -ClassName MyServiceStatus
    
  • WBEMTest (legacy WMI tool—MI is backward-compatible, so this will work too).

Key Notes

  • Permissions: Run the provider host with an account that has access to query NT service status (Local System works well for this).
  • Decoupling: Since this provider runs as a separate process, it won't impact your NT services if it encounters issues. You can even deploy it to a separate server if needed.
  • Monitoring Compatibility: Most modern monitoring tools support MI directly, but if yours only uses WMI v1, it will still be able to query your MI provider thanks to backward compatibility.

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:44:48