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

.NET 5.0环境下不使用WMI提取磁盘性能数据的可行方案

Alternative Ways to Get Disk Performance Metrics in .NET 5 Without WMI

Great question! Since WMI is unavailable in your Jenkins environment (and installing .NET Framework isn't feasible), you have a couple of reliable options to fetch those disk performance metrics like ReadTimes, IdleTimes, WriteTimes, and AvgDiscSec per Read. Let's break them down:

1. Use .NET's Native PerformanceCounter Class

The System.Diagnostics.PerformanceCounter is a built-in .NET component that directly interfaces with Windows' Performance Counters—no WMI required. This is the most straightforward approach since it doesn't need external dependencies.

How It Works

Windows maintains a set of performance counters for physical disks, including exactly the metrics you need. You'll need to:

  • Target the PhysicalDisk counter category.
  • Enumerate instances for each individual disk (skip _Total if you want per-disk data).
  • Fetch the relevant counters, and for cumulative metrics like ReadTimes, calculate the difference between two sample points (since counters return raw cumulative values).

Code Example

using System;
using System.Diagnostics;

public class DiskMetricsCollector
{
    public static void CollectDiskMetrics()
    {
        var diskCategory = new PerformanceCounterCategory("PhysicalDisk");
        string[] diskInstances = diskCategory.GetInstanceNames();

        foreach (var instance in diskInstances)
        {
            // Skip the total aggregate instance if you want per-disk data
            if (instance.Equals("_Total", StringComparison.OrdinalIgnoreCase))
                continue;

            Console.WriteLine($"--- Disk Instance: {instance} ---");

            // Get Avg. Disk sec/Read (direct value)
            using var avgReadSecCounter = new PerformanceCounter(
                "PhysicalDisk", "Avg. Disk sec/Read", instance, true);
            float avgReadSec = avgReadSecCounter.NextValue();
            Console.WriteLine($"Avg. Disk sec per Read: {avgReadSec:F6}");

            // Get cumulative Read Time (calculate difference over 1 second)
            using var readTimeRawCounter = new PerformanceCounter(
                "PhysicalDisk", "Disk Read Time", instance, true);
            long firstRawValue = readTimeRawCounter.RawValue;
            System.Threading.Thread.Sleep(1000); // Wait to capture a delta
            long secondRawValue = readTimeRawCounter.RawValue;
            long readTimeDelta = secondRawValue - firstRawValue;
            double readTimeSeconds = readTimeDelta / (double)Stopwatch.Frequency;
            Console.WriteLine($"Read Time (last 1s): {readTimeSeconds:F2}s");

            // Repeat similar logic for other metrics:
            // - Disk Write Time (for WriteTimes)
            // - Disk Idle Time (for IdleTimes)
        }
    }
}

Notes

  • Make sure your Jenkins service account has Performance Monitor Users permissions to access these counters.
  • Some counter names might vary slightly by Windows version—verify them using the Windows Performance Monitor tool (perfmon.exe).

2. Use a Third-Party Library for PDH API Access

If you prefer a more streamlined or flexible approach, you can use a third-party NuGet library that wraps the Windows Performance Data Helper (PDH) API (the underlying system API that PerformanceCounter uses). One popular option is PdhSharp.

How to Use It

  1. Install the NuGet package:
    Install-Package PdhSharp
    
  2. Use the library to query counters directly:
using PdhSharp;
using System;

public class PdhDiskMetricsCollector
{
    public static void CollectMetrics()
    {
        using var query = new PdhQuery();
        
        // Add counters for a specific disk instance (replace "0 C:" with your disk instance)
        var avgReadCounter = query.AddCounter(@"\PhysicalDisk(0 C:)\Avg. Disk sec/Read");
        var readTimeCounter = query.AddCounter(@"\PhysicalDisk(0 C:)\Disk Read Time");

        // Collect initial data
        query.CollectQueryData();
        float initialAvgRead = avgReadCounter.GetValue();
        long initialReadTime = readTimeCounter.GetRawValue();

        // Wait and collect again to calculate delta
        System.Threading.Thread.Sleep(1000);
        query.CollectQueryData();
        float updatedAvgRead = avgReadCounter.GetValue();
        long updatedReadTime = readTimeCounter.GetRawValue();

        Console.WriteLine($"Avg. Disk sec per Read: {updatedAvgRead:F6}");
        double readTimeSeconds = (updatedReadTime - initialReadTime) / (double)Stopwatch.Frequency;
        Console.WriteLine($"Read Time (last 1s): {readTimeSeconds:F2}s");
    }
}

Benefits

  • More control over counter queries compared to the built-in PerformanceCounter.
  • Avoids some edge cases with the .NET class, like instance name parsing issues.

3. Direct P/Invoke to Windows PDH API (Advanced)

If you want full control without any dependencies (even the built-in PerformanceCounter), you can directly call the PDH API via P/Invoke. This is more code-heavy but gives you complete flexibility over how you fetch and process metrics.

You'd need to declare P/Invoke methods for functions like PdhOpenQuery, PdhAddCounter, PdhCollectQueryData, and PdhGetFormattedCounterValue. While this works, it's generally overkill unless you have specific needs that the above methods don't meet.


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 11:07:50