Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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 ([email protected])
// 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

like image 718
user1120389 Avatar asked Dec 29 '11 04:12

user1120389


People also ask

What can C be used for?

C is a powerful general-purpose programming language. It can be used to develop software like operating systems, databases, compilers, and so on. C programming is an excellent language to learn to program for beginners. Our C tutorials will guide you to learn C programming one step at a time.

How do I use C on my computer?

It is a bit more cryptic in its style than some other languages, but you get beyond that fairly quickly. C is what is called a compiled language. This means that once you write your C program, you must run it through a C compiler to turn your program into an executable that the computer can run (execute).

How do I start programming with C?

To start using C, you need two things: A text editor, like Notepad, to write C code. A compiler, like GCC, to translate the C code into a language that the computer will understand.


1 Answers

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)

like image 70
TheLegendaryCopyCoder Avatar answered Oct 17 '22 20:10

TheLegendaryCopyCoder