Permalink
Cannot retrieve contributors at this time
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?
RetrieveSMARTData/Program.cs
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
184 lines (166 sloc)
6.43 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// (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(); | |
} | |
} | |
} |