1

我找到了以下用于处理硬盘 SMART 数据的代码。见:http ://en.wikipedia.org/wiki/SMART 。

// (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);
            }
        }
    }
}

但我不明白如何解析 Value 打印的Console.Write("{0} :{1} : ", b.AttributeType, b.Value);

我知道这是某种标准化值。

但如果我的温度是 187。这是什么意思?

4

1 回答 1

3

b.VendorData保存您要查找的数据字节数组。该数据在foreach循环中以十六进制格式显示。第一个值是驱动器的当前温度。如果要获得正确的温度,则需要将数组中的第一个字节转换为数字...

温度:100:24 0 d 0 33 0 0 65

24 是从字节转换而来的 HEX 值,并保存以摄氏度 (36 °C) 为单位的温度值。您可以使用下面的示例将 byte 转换为 int。

int 温度 = Convert.ToInt32(b.VendorData[0]);

于 2013-05-10T10:28:27.823 回答