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

如何在Windows系统中获取NVMe设备的S.M.A.R.T.数据

可行获取方案汇总

方案1:PowerShell原生方案(无需额外依赖)

Windows 10 1903及以上版本可直接使用内置存储类获取NVMe SMART数据,需管理员权限运行PowerShell:

  • 获取基础健康信息命令:
# 获取所有NVMe磁盘的SMART统计数据
Get-PhysicalDisk | Where-Object {$_.MediaType -eq 'SSD' -and $_.BusType -eq 'NVMe'} | Get-StorageReliabilityCounter
  • 导出完整结构化属性的进阶脚本:
$nvmeDisks = Get-CimInstance -Namespace root\Microsoft\Windows\Storage -ClassName MSFT_PhysicalDisk | Where-Object {$_.BusType -eq 17} # 17为NVMe总线类型对应编号
foreach ($disk in $nvmeDisks) {
    $reliability = Get-CimAssociatedInstance -InputObject $disk -ResultClassName MSFT_StorageReliabilityCounter
    [PSCustomObject]@{
        磁盘型号 = $disk.FriendlyName
        序列号 = $disk.SerialNumber
        健康状态 = $disk.HealthStatus
        当前温度 = $reliability.Temperature
        累计写入字节 = $reliability.TotalBytesWritten
        累计读取字节 = $reliability.TotalBytesRead
        通电总时长 = $reliability.PowerOnHours
        不安全关机次数 = $reliability.UnsafeShutdownCount
    }
}

方案2:免开发工具方案

无需自行编码的场景可直接使用smartctl工具,安装对应Windows版本后运行以下命令即可输出全量SMART数据:

smartctl -a /dev/nvme0

其中nvme0对应系统识别的第一块NVMe磁盘,多磁盘可依次替换为nvme1、nvme2等。

方案3:可直接运行的C#代码方案(对应Windows官方API实现)

以下代码兼容Windows 10及以上版本,需以管理员权限运行,.NET Framework 4.5+、.NET Core 3.0+均可直接编译:

using System;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;

public class NvmeSmartReader
{
    private const uint IOCTL_STORAGE_QUERY_PROPERTY = 0x2D1400;
    private const uint StorageAdapterProtocolSpecificProperty = 0x15;
    private const uint PropertyStandardQuery = 0;
    private const byte NVME_PROTOCOL_TYPE = 0x1E;
    private const uint NVME_LOG_PAGE_SMART = 0x2;

    [StructLayout(LayoutKind.Sequential)]
    private struct STORAGE_PROPERTY_QUERY
    {
        public uint PropertyId;
        public uint QueryType;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public byte[] AdditionalParameters;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct STORAGE_PROTOCOL_SPECIFIC_DATA
    {
        public uint ProtocolType;
        public uint DataType;
        public uint ProtocolDataRequestValue;
        public uint ProtocolDataRequestSubValue;
        public uint ProtocolDataOffset;
        public uint ProtocolDataLength;
        public uint FixedProtocolReturnData;
        public uint Reserved;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct NVME_SMART_INFO
    {
        public byte CriticalWarning;
        public ushort CompositeTemperature;
        public byte AvailableSpare;
        public byte AvailableSpareThreshold;
        public byte PercentageUsed;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)]
        public byte[] Reserved1;
        public ulong DataUnitsRead;
        public ulong DataUnitsWritten;
        public ulong HostReadCommands;
        public ulong HostWriteCommands;
        public ulong ControllerBusyTime;
        public ulong PowerCycles;
        public ulong PowerOnHours;
        public ulong UnsafeShutdowns;
        public ulong MediaErrors;
        public ulong NumErrLogEntries;
    }

    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool DeviceIoControl(SafeFileHandle hDevice, uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, IntPtr lpOutBuffer, uint nOutBufferSize, out uint lpBytesReturned, IntPtr lpOverlapped);

    [DllImport("kernel32.dll")]
    private static extern void ZeroMemory(IntPtr dst, int length);

    public static NVME_SMART_INFO ReadNvmeSmart(int diskNumber)
    {
        string path = $"\\\\.\\PhysicalDrive{diskNumber}";
        var handle = CreateFile(path, 0x80000000 | 0x40000000, 0x1 | 0x2, IntPtr.Zero, 3, 0, IntPtr.Zero);
        if (handle.IsInvalid) throw new System.ComponentModel.Win32Exception();

        int querySize = Marshal.SizeOf(typeof(STORAGE_PROPERTY_QUERY)) + Marshal.SizeOf(typeof(STORAGE_PROTOCOL_SPECIFIC_DATA));
        IntPtr queryBuffer = Marshal.AllocHGlobal(querySize);
        ZeroMemory(queryBuffer, querySize);

        STORAGE_PROPERTY_QUERY query = new STORAGE_PROPERTY_QUERY();
        query.PropertyId = StorageAdapterProtocolSpecificProperty;
        query.QueryType = PropertyStandardQuery;
        Marshal.StructureToPtr(query, queryBuffer, false);

        STORAGE_PROTOCOL_SPECIFIC_DATA protocolData = new STORAGE_PROTOCOL_SPECIFIC_DATA();
        protocolData.ProtocolType = NVME_PROTOCOL_TYPE;
        protocolData.DataType = NVME_LOG_PAGE_SMART;
        protocolData.ProtocolDataRequestValue = NVME_LOG_PAGE_SMART;
        protocolData.ProtocolDataOffset = (uint)Marshal.SizeOf(typeof(STORAGE_PROPERTY_QUERY)) + (uint)Marshal.SizeOf(typeof(STORAGE_PROTOCOL_SPECIFIC_DATA));
        protocolData.ProtocolDataLength = (uint)Marshal.SizeOf(typeof(NVME_SMART_INFO));
        Marshal.StructureToPtr(protocolData, queryBuffer + Marshal.SizeOf(typeof(STORAGE_PROPERTY_QUERY)), false);

        uint outputSize = (uint)(querySize + Marshal.SizeOf(typeof(NVME_SMART_INFO)));
        IntPtr outputBuffer = Marshal.AllocHGlobal((int)outputSize);
        ZeroMemory(outputBuffer, (int)outputSize);

        bool success = DeviceIoControl(handle, IOCTL_STORAGE_QUERY_PROPERTY, queryBuffer, (uint)querySize, outputBuffer, outputSize, out uint bytesReturned, IntPtr.Zero);
        if (!success) throw new System.ComponentModel.Win32Exception();

        NVME_SMART_INFO smartInfo = Marshal.PtrToStructure<NVME_SMART_INFO>(outputBuffer + querySize);
        
        Marshal.FreeHGlobal(queryBuffer);
        Marshal.FreeHGlobal(outputBuffer);
        handle.Close();

        return smartInfo;
    }

    // 调用示例
    public static void Main()
    {
        // 磁盘编号可在系统磁盘管理中查看,0为第一块物理磁盘
        var smartData = ReadNvmeSmart(0);
        Console.WriteLine($"当前温度:{smartData.CompositeTemperature - 273}℃");
        Console.WriteLine($"通电总时长:{smartData.PowerOnHours} 小时");
        Console.WriteLine($"累计写入量:{smartData.DataUnitsWritten * 512 / 1024 / 1024 / 1024} GB");
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 11:27:03