How can I use C# To read extended smart data?

两盒软妹~` 提交于 2019-12-30 06:57:06

问题


I know a bit of C++ and Java, but am wanting to learn c# on my own. To mess with, I'm trying to read the SMART data of my hard drive. I have this C# Code, but I do not know how to modify it to read an additional memory value: It apparently reads the 'Value' value but not the 'Worst' or 'Threshold' value. I want to add these two data values (Worst and Threshold) to the program. Figuring how to do this will help me learn C# a little.

C# Example: (What I want to use)

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

}

The big problem is in figuring out what it all means as it really is “vendor specific”. The data is organised into 12 byte blocks of attribute data. The first byte of the array gives the number of attribute blocks. Each attribute block has the format:

Item Data -0 and 1Unknown usually zero -2 Attribute -3 Status -4 Unknown usually zero -5 Value -6 Worst -7,8 Raw Value -9,10,11 Unknown usually zero

I found these here: http://www.i-programmer.info/projects/38-windows/208-disk-drive-dangers.html?start=2


回答1:


Note that not all SMART HDD info can be obtained from a single WMI query.

You need to query all the following to determine the current value, worst value, threshold, drive status and attribute status:

  • Win32_DiskDrive
  • MSStorageDriver_FailurePredictStatus
  • MSStorageDriver_FailurePredictData
  • MSStorageDriver_FailurePredictThresholds

For a comprehensive solution in C#/WMI detailing all relevant SMART HDD info see this solution http://www.know24.net/blog/C+WMI+HDD+SMART+Information.aspx (please note: I own this development blog)



来源:https://stackoverflow.com/questions/8663980/how-can-i-use-c-sharp-to-read-extended-smart-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!