Skip to content
Permalink
6a49ba6ea1
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
184 lines (166 sloc) 6.43 KB
// (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 {
Raw_Read_Error_Rate = 0x01,
Throughput_Performance = 0x02,
Spin_Up_Time = 0x03,
Start_Stop_Count = 0x04,
Reallocated_Sectors_Count = 0x05,
Read_Channel_Margin = 0x06,
Seek_Error_Rate = 0x07,
Seek_Time_Performance = 0x08,
Power_On_Hours = 0x09,
Spin_Retry_Count = 0x0A,
SSD_Program_Fail_Count = 0xAB,
SSD_Erase_Fail_Count = 0xAC,
SSD_Wear_Leveling_Count = 0xAD,
Calibration_Retry_Count = 0x0B,
Unused_Reserved_Block_Count_Total = 0xB4,
Power_Cycle_Count = 0x0C,
Soft_Read_Error_Rate = 0x0D,
SATA_Downshift_Error_Count = 0xB7,
End_to_End_error = 0xB8,
Head_Stability = 0xB9,
Induced_Op_Vibration_Detection = 0xBA,
Reported_Uncorrectable_Errors = 0xBB,
Command_Timeout = 0xBC,
High_Fly_Writes = 0xBD,
Airflow_Temperature_WDC = 0xBE,
Temperature_Difference_from_100 = 0xBE,
GSense_Error_Rate = 0xBF,
Poweroff_Retract_Count = 0xC0,
Load_Cycle_Count = 0xC1,
Temperature = 0xC2,
Hardware_ECC_Recovered = 0xC3,
Reallocation_Event_Count = 0xC4,
Current_Pending_Sector_Count = 0xC5,
Uncorrectable_Sector_Count = 0xC6,
Ultra_DMACRC_Error_Count = 0xC7,
Multi_Zone_Error_Rate = 0xC8,
Write_Error_Rate_Fujitsu = 0xC8,
Off_Track_Soft_Read_Error_Rate = 0xC9,
Data_Address_Markerrors = 0xCA,
Run_Out_Cancel = 0xCB,
Soft_ECC_Correction = 0xCC,
Thermal_Asperity_Rate_TAR = 0xCD,
Flying_Height = 0xCE,
Spin_High_Current = 0xCF,
Spin_Buzz = 0xD0,
Offline_Seek_Performance = 0xD1,
Vibration_During_Write = 0xD3,
Shock_During_Write = 0xD4,
Disk_Shift = 0xDC,
GSense_Error_Rate_Alt = 0xDD,
Loaded_Hours = 0xDE,
Load_Unload_Retry_Count = 0xDF,
Load_Friction = 0xE0,
Load_Unload_Cycle_Count = 0xE1,
Load_In_Time = 0xE2,
Torque_Amplification_Count = 0xE3,
Power_Off_Retract_Cycle = 0xE4,
GMR_Head_Amplitude = 0xE6,
Drive_Temperature = 0xE7,
Head_Flying_Hours = 0xF0,
Transfer_Error_Rate_Fujitsu = 0xF0,
Total_LBAs_Written = 0xF1,
Total_LBAs_Read = 0xF2,
Read_Error_Retry_Rate = 0xFA,
Free_Fall_Protection = 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.VendorData[0]);
Console.WriteLine();
}
}
} catch (ManagementException e) {
Console.WriteLine("An error occurred while querying for WMI data: " + e.Message);
}
Console.ReadLine();
}
}
}