After some work, I compiled a code returning a comprehensive report of all relevant SMART data for the hard drive using C # / WMI.
As shown in the figure here , this is the code:
using System;
using System.Collections.Generic;
using System.Management;
public class HDD
{
public int Index { get; set; }
public bool IsOK { get; set; }
public string Model { get; set; }
public string Type { get; set; }
public string Serial { get; set; }
public Dictionary<int, Smart> Attributes = new Dictionary<int, Smart>() {
{0x00, new Smart("Invalid")},
{0x01, new Smart("Raw read error rate")},
{0x02, new Smart("Throughput performance")},
{0x03, new Smart("Spinup time")},
{0x04, new Smart("Start/Stop count")},
{0x05, new Smart("Reallocated sector count")},
{0x06, new Smart("Read channel margin")},
{0x07, new Smart("Seek error rate")},
{0x08, new Smart("Seek timer performance")},
{0x09, new Smart("Power-on hours count")},
{0x0A, new Smart("Spinup retry count")},
{0x0B, new Smart("Calibration retry count")},
{0x0C, new Smart("Power cycle count")},
{0x0D, new Smart("Soft read error rate")},
{0xB8, new Smart("End-to-End error")},
{0xBE, new Smart("Airflow Temperature")},
{0xBF, new Smart("G-sense error rate")},
{0xC0, new Smart("Power-off retract count")},
{0xC1, new Smart("Load/Unload cycle count")},
{0xC2, new Smart("HDD temperature")},
{0xC3, new Smart("Hardware ECC recovered")},
{0xC4, new Smart("Reallocation count")},
{0xC5, new Smart("Current pending sector count")},
{0xC6, new Smart("Offline scan uncorrectable count")},
{0xC7, new Smart("UDMA CRC error rate")},
{0xC8, new Smart("Write error rate")},
{0xC9, new Smart("Soft read error rate")},
{0xCA, new Smart("Data Address Mark errors")},
{0xCB, new Smart("Run out cancel")},
{0xCC, new Smart("Soft ECC correction")},
{0xCD, new Smart("Thermal asperity rate (TAR)")},
{0xCE, new Smart("Flying height")},
{0xCF, new Smart("Spin high current")},
{0xD0, new Smart("Spin buzz")},
{0xD1, new Smart("Offline seek performance")},
{0xDC, new Smart("Disk shift")},
{0xDD, new Smart("G-sense error rate")},
{0xDE, new Smart("Loaded hours")},
{0xDF, new Smart("Load/unload retry count")},
{0xE0, new Smart("Load friction")},
{0xE1, new Smart("Load/Unload cycle count")},
{0xE2, new Smart("Load-in time")},
{0xE3, new Smart("Torque amplification count")},
{0xE4, new Smart("Power-off retract count")},
{0xE6, new Smart("GMR head amplitude")},
{0xE7, new Smart("Temperature")},
{0xF0, new Smart("Head flying hours")},
{0xFA, new Smart("Read error retry rate")},
};
}
public class Smart
{
public bool HasData
{
get
{
if (Current == 0 && Worst == 0 && Threshold == 0 && Data == 0)
return false;
return true;
}
}
public string Attribute { get; set; }
public int Current { get; set; }
public int Worst { get; set; }
public int Threshold { get; set; }
public int Data { get; set; }
public bool IsOK{ get; set; }
public Smart()
{
}
public Smart(string attributeName)
{
this.Attribute = attributeName;
}
}
public class Program
{
public static void Main()
{
try
{
var dicDrives = new Dictionary<int, HDD>();
var wdSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
int iDriveIndex = 0;
foreach (ManagementObject drive in wdSearcher.Get())
{
var hdd = new HDD();
hdd.Model = drive["Model"].ToString().Trim();
hdd.Type = drive["InterfaceType"].ToString().Trim();
dicDrives.Add(iDriveIndex, hdd);
iDriveIndex++;
}
var pmsearcher = new ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMedia");
iDriveIndex = 0;
foreach (ManagementObject drive in pmsearcher.Get())
{
if (iDriveIndex >= dicDrives.Count)
break;
dicDrives[iDriveIndex].Serial = drive["SerialNumber"] == null ? "None" : drive["SerialNumber"].ToString().Trim();
iDriveIndex++;
}
var searcher = new ManagementObjectSearcher("Select * from Win32_DiskDrive");
searcher.Scope = new ManagementScope(@"\root\wmi");
searcher.Query = new ObjectQuery("Select * from MSStorageDriver_FailurePredictStatus");
iDriveIndex = 0;
foreach (ManagementObject drive in searcher.Get())
{
dicDrives[iDriveIndex].IsOK = (bool)drive.Properties["PredictFailure"].Value == false;
iDriveIndex++;
}
searcher.Query = new ObjectQuery("Select * from MSStorageDriver_FailurePredictData");
iDriveIndex = 0;
foreach (ManagementObject data in searcher.Get())
{
Byte[] bytes = (Byte[])data.Properties["VendorSpecific"].Value;
for (int i = 0; i < 30; ++i)
{
try
{
int id = bytes[i*12 + 2];
int flags = bytes[i * 12 + 4];
bool failureImminent = (flags & 0x1) == 0x1;
int value = bytes[i*12 + 5];
int worst = bytes[i*12 + 6];
int vendordata = BitConverter.ToInt32(bytes, i*12 + 7);
if (id == 0) continue;
var attr = dicDrives[iDriveIndex].Attributes[id];
attr.Current = value;
attr.Worst = worst;
attr.Data = vendordata;
attr.IsOK = failureImminent == false;
}
catch
{
}
}
iDriveIndex++;
}
searcher.Query = new ObjectQuery("Select * from MSStorageDriver_FailurePredictThresholds");
iDriveIndex = 0;
foreach (ManagementObject data in searcher.Get())
{
Byte[] bytes = (Byte[])data.Properties["VendorSpecific"].Value;
for (int i = 0; i < 30; ++i)
{
try
{
int id = bytes[i*12 + 2];
int thresh = bytes[i*12 + 3];
if (id == 0) continue;
var attr = dicDrives[iDriveIndex].Attributes[id];
attr.Threshold = thresh;
}
catch
{
}
}
iDriveIndex++;
}
foreach (var drive in dicDrives)
{
Console.WriteLine("-----------------------------------------------------");
Console.WriteLine(" DRIVE ({0}): " + drive.Value.Serial + " - " + drive.Value.Model + " - " + drive.Value.Type, ((drive.Value.IsOK) ? "OK" : "BAD"));
Console.WriteLine("-----------------------------------------------------");
Console.WriteLine("");
Console.WriteLine("ID Current Worst Threshold Data Status");
foreach (var attr in drive.Value.Attributes)
{
if (attr.Value.HasData)
Console.WriteLine("{0}\t {1}\t {2}\t {3}\t " + attr.Value.Data + " " + ((attr.Value.IsOK) ? "OK" : ""), attr.Value.Attribute, attr.Value.Current, attr.Value.Worst, attr.Value.Threshold);
}
Console.WriteLine();
Console.WriteLine();
Console.WriteLine();
}
Console.ReadLine();
}
catch (ManagementException e)
{
Console.WriteLine("An error occurred while querying for WMI data: " + e.Message);
}
}
}
- 19 2017 .
, . .
GitHub Repo: Smart.Net
:
var drives = Simplified.IO.Smart.GetDrives();