c# - 如何使用 C# 读取扩展的智能数据?

标签 c# .net windows disk-smart

我懂一点 C++ 和 Java,但我想自学 C#。搞砸了,我正在尝试读取硬盘驱动器的 SMART 数据。我有这个 C# 代码,但我不知道如何修改它以读取额外的内存值:它显然读取“值”值而不是“最差”或“阈值”值。我想将这两个数据值(最差和阈值)添加到程序中。弄清楚如何执行此操作将帮助我稍微学习 C#。

C# 示例:(我想使用的)

// (c) Microsoft Corporation
// Author: Clemens Vasters (clemensv@microsoft.com)
// Code subject to MS-PL: http://opensource.org/licenses/ms-pl.html 
// SMART Attributes and Background: http://en.wikipedia.org/wiki/S.M.A.R.T.
// SMART Attributes Overview: http://www.t13.org/Documents/UploadedDocuments/docs2005/e05171r0-ACS-SMARTAttributes_Overview.pdf

namespace SmartDataApp
{
using System;
using System.Collections.Generic;
using System.Management;
using System.Runtime.InteropServices;

public enum SmartAttributeType : byte
{
    ReadErrorRate = 0x01,
    ThroughputPerformance = 0x02,
    SpinUpTime = 0x03,
    StartStopCount = 0x04,
    ReallocatedSectorsCount = 0x05,
    ReadChannelMargin = 0x06,
    SeekErrorRate = 0x07,
    SeekTimePerformance = 0x08,
    PowerOnHoursPOH = 0x09,
    SpinRetryCount = 0x0A,
    CalibrationRetryCount = 0x0B,
    PowerCycleCount = 0x0C,
    SoftReadErrorRate = 0x0D,
    SATADownshiftErrorCount = 0xB7,
    EndtoEnderror = 0xB8,
    HeadStability = 0xB9,
    InducedOpVibrationDetection = 0xBA,
    ReportedUncorrectableErrors = 0xBB,
    CommandTimeout = 0xBC,
    HighFlyWrites = 0xBD,
    AirflowTemperatureWDC = 0xBE,
    TemperatureDifferencefrom100 = 0xBE,
    GSenseErrorRate = 0xBF,
    PoweroffRetractCount = 0xC0,
    LoadCycleCount = 0xC1,
    Temperature = 0xC2,
    HardwareECCRecovered = 0xC3,
    ReallocationEventCount = 0xC4,
    CurrentPendingSectorCount = 0xC5,
    UncorrectableSectorCount = 0xC6,
    UltraDMACRCErrorCount = 0xC7,
    MultiZoneErrorRate = 0xC8,
    WriteErrorRateFujitsu = 0xC8,
    OffTrackSoftReadErrorRate = 0xC9,
    DataAddressMarkerrors = 0xCA,
    RunOutCancel = 0xCB,
    SoftECCCorrection = 0xCC,
    ThermalAsperityRateTAR = 0xCD,
    FlyingHeight = 0xCE,
    SpinHighCurrent = 0xCF,
    SpinBuzz = 0xD0,
    OfflineSeekPerformance = 0xD1,
    VibrationDuringWrite = 0xD3,
    ShockDuringWrite = 0xD4,
    DiskShift = 0xDC,
    GSenseErrorRateAlt = 0xDD,
    LoadedHours = 0xDE,
    LoadUnloadRetryCount = 0xDF,
    LoadFriction = 0xE0,
    LoadUnloadCycleCount = 0xE1,
    LoadInTime = 0xE2,
    TorqueAmplificationCount = 0xE3,
    PowerOffRetractCycle = 0xE4,
    GMRHeadAmplitude = 0xE6,
    DriveTemperature = 0xE7,
    HeadFlyingHours = 0xF0,
    TransferErrorRateFujitsu = 0xF0,
    TotalLBAsWritten = 0xF1,
    TotalLBAsRead = 0xF2,
    ReadErrorRetryRate = 0xFA,
    FreeFallProtection = 0xFE,
}

public class SmartData
{
    readonly Dictionary<SmartAttributeType, SmartAttribute> attributes;
    readonly ushort structureVersion;

    public SmartData(byte[] arrVendorSpecific)
    {
        attributes = new Dictionary<SmartAttributeType, SmartAttribute>();
        for (int offset = 2; offset < arrVendorSpecific.Length; )
        {
            var a = FromBytes<SmartAttribute>(arrVendorSpecific, ref offset, 12);
            // Attribute values 0x00, 0xfe, 0xff are invalid
            if (a.AttributeType != 0x00 && (byte)a.AttributeType != 0xfe && (byte)a.AttributeType != 0xff)
            {
                attributes[a.AttributeType] = a;
            }
        }
        structureVersion = (ushort)(arrVendorSpecific[0] * 256 + arrVendorSpecific[1]);
    }

    public ushort StructureVersion
    {
        get
        {
            return this.structureVersion;
        }
    }

    public SmartAttribute this[SmartAttributeType v]
    {
        get
        {
            return this.attributes[v];
        }
    }

    public IEnumerable<SmartAttribute> Attributes
    {
        get
        {
            return this.attributes.Values;
        }
    }

    static T FromBytes<T>(byte[] bytearray, ref int offset, int count)
    {
        IntPtr ptr = IntPtr.Zero;

        try
        {
            ptr = Marshal.AllocHGlobal(count);
            Marshal.Copy(bytearray, offset, ptr, count);
            offset += count;
            return (T)Marshal.PtrToStructure(ptr, typeof(T));
        }
        finally
        {
            if (ptr != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(ptr);
            }
        }
    }
}

[StructLayout(LayoutKind.Sequential)]
public struct SmartAttribute
{
    public SmartAttributeType AttributeType;
    public ushort Flags;
    public byte Value;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
    public byte[] VendorData;

    public bool Advisory
    {
        get
        {
            return (Flags & 0x1) == 0x0; // Bit 0 unset?
        }
    }
    public bool FailureImminent
    {
        get
        {
            return (Flags & 0x1) == 0x1; // Bit 0 set?
        }
    }
    public bool OnlineDataCollection
    {
        get
        {
            return (Flags & 0x2) == 0x2; // Bit 0 set?
        }
    }

}

public class Program
{
    public static void Main()
    {
        try
        {
            var searcher = new ManagementObjectSearcher("root\\WMI", "SELECT * FROM MSStorageDriver_ATAPISmartData");

            foreach (ManagementObject queryObj in searcher.Get())
            {
                Console.WriteLine("-----------------------------------");
                Console.WriteLine("MSStorageDriver_ATAPISmartData instance");
                Console.WriteLine("-----------------------------------");

                var arrVendorSpecific = (byte[])queryObj.GetPropertyValue("VendorSpecific");

                // Create SMART data from 'vendor specific' array
                var d = new SmartData(arrVendorSpecific);
                foreach (var b in d.Attributes)
                {
                    Console.Write("{0} :{1} : ", b.AttributeType, b.Value);
                    foreach (byte vendorByte in b.VendorData)
                    {
                        Console.Write("{0:x} ", vendorByte);
                    }
                    Console.WriteLine();
                }

            }
        }
        catch (ManagementException e)
        {
            Console.WriteLine("An error occurred while querying for WMI data: " + e.Message);
        }
    }
}

最大的问题是弄清楚这一切意味着什么,因为它确实是“供应商特定的”。数据被组织成 12 字节的属性数据 block 。数组的第一个字节给出了属性 block 的数量。每个属性 block 的格式为:

项目数据 -0 和 1Unknown 通常为零 -2 属性 -3 状态 -4 未知 通常为零 -5 值 -6 最差 -7,8 原始值 -9,10,11 未知 通常为零

我在这里找到了这些:http://www.i-programmer.info/projects/38-windows/208-disk-drive-dangers.html?start=2

最佳答案

请注意,并非所有 SMART HDD 信息都可以从单个 WMI 查询中获取。

您需要查询以下所有内容以确定当前值、最差值、阈值、驱动状态和属性状态:

  • Win32_DiskDrive
  • MSStorageDriver_FailurePredictStatus
  • MSStorageDriver_FailurePredictData
  • MSStorageDriver_FailurePredictThresholds

有关 C#/WMI 中详细说明所有相关 SMART HDD 信息的综合解决方案,请参阅此解决方案 http://www.know24.net/blog/C+WMI+HDD+SMART+Information.aspx (请注意:我拥有这个开发博客)

关于c# - 如何使用 C# 读取扩展的智能数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8663980/

相关文章:

c# - DOC 到 PDF 库(不一定免费)

c# - 强制重新加载 XAML 页面

c# - 对于在 ASP.Net WebAPI 应用程序中存储枚举的位置是否有任何约定?

c# - 使用 IF 语句选择 session 变量

c# - 自定义控件导致 Visual Studio 2008 崩溃

java - 无法生成有效的网页。引用

mysql - .Net Core 2.0 Database First Approach Scaffold-Mysql DB的DbContext

c# - 某些服务在未被其他服务使用时会自动停止

windows - 如何强制 Windows godoc 在 golang 中更新本地网络服务器上的私有(private)包文档?

c# - 适用于 Windows + C# 的短信网关