samedi 20 février 2016

SMART HDD/SSD : Obtenir les infos SMART d'un disque dur

Travaillant actuellement sur un projet d'optimisation HDD/SSD, cela a nécessité de récupérer les informations SMART d'un disque dur de type SSD ou HDD en s'appuyant sur les objets WMI :

Voilà à quoi pourrait ressembler une telle librairie avec l'espace de nom "Smart" (en c#) :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;
 
namespace Smart
{
    public class Infos
    {
 
        public byte[] VendorSpecByte { get; set; }
        public string InstanceN { get; set; }
        public List Datas { get; set; }
 
        public Infos()
        {
            Datas = new List();
            LoadInfos();
        }
 
        private void LoadInfos()
        {
            using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\WMI", "SELECT VendorSpecific, InstanceName FROM MSStorageDriver_FailurePredictData"))
            {
                foreach (ManagementObject data in searcher.Get())
                {
                    try
                    {
                        this.VendorSpecByte = (byte[])data.GetPropertyValue("VendorSpecific");
                        this.InstanceN = (string)data.GetPropertyValue("InstanceName");
                        for (int i = 0; i <= 29; i++)
                        {
                            int id = VendorSpecByte[i * 12 + 2];
                            int flags = VendorSpecByte[i * 12 + 4];
                            bool failureImminent = (flags & 0x1) == 0x1;
                            UInt32 vendordata = BitConverter.ToUInt32(VendorSpecByte, i * 12 + 7);
                            if (!(id == 0))
                            {
                                PropertyContent pInfos = new PropertyContent();
                                pInfos.Id = id;
                                pInfos.Value = Convert.ToString(vendordata);
                                pInfos.IsOk = (failureImminent == false);
                                this.Datas.Add(pInfos);
                            }
                        }
                    }
                    catch (ManagementException ex)
                    {
                        throw new ManagementException("Erreur WMI", ex);
                    }
                }
            }
        }
 
        public string FormatToString()
        {
            string str = String.Empty;
            foreach (PropertyContent d in Datas)
            {
                str += ("ID:"
                             + (d.Id + ("\r\n" + ("PropertyName:"
                             + (d.PropertyName + ("\r\n" + ("PropertyValue:"
                             + (d.Value + ("\r\n" + ("PropertyState:"
                             + (Convert.ToString(d.IsOk) + "\r\n")))))))))));
            }
 
            return str;
        }
 
    }
 
    public class PropertyContent
    {
 
        private int m_Id;
        public int Id
        {
            get { return m_Id; }
            set
            {
                m_Id = value;
                switch (m_Id)
                {
                    case 1:
                        m_PropertyName = PropertyNames.RawReadErrorRate;
                        break;
                    case 2:
                        m_PropertyName = PropertyNames.ThroughputPerformance;
                        break;
                    case 3:
                        m_PropertyName = PropertyNames.SpinUpTime;
                        break;
                    case 4:
                        m_PropertyName = PropertyNames.StartStopCount;
                        break;
                    case 5:
                        m_PropertyName = PropertyNames.ReallocatedSectorCount;
                        break;
                    case 6:
                        m_PropertyName = PropertyNames.ReadChannelMargin;
                        break;
                    case 7:
                        m_PropertyName = PropertyNames.SeekErrorRate;
                        break;
                    case 8:
                        m_PropertyName = PropertyNames.SeekTimePerformance;
                        break;
                    case 9:
                        m_PropertyName = PropertyNames.PowerOnHours;
                        break;
                    case 10:
                        m_PropertyName = PropertyNames.SpinRetryCount;
                        break;
                    case 11:
                        m_PropertyName = PropertyNames.CalibrationRetryCount;
                        break;
                    case 12:
                        m_PropertyName = PropertyNames.PowerCycleCount;
                        break;
                    case 171:
                        m_PropertyName = PropertyNames.ProgramFailBlockCount;
                        break;
                    case 172:
                        m_PropertyName = PropertyNames.EraseFailBlockCount;
                        break;
                    case 173:
                        m_PropertyName = PropertyNames.UnknownAttribute;
                        break;
                    case 174:
                        m_PropertyName = PropertyNames.UnexpectedPowerLossCount;
                        break;
                    case 187:
                        m_PropertyName = PropertyNames.ReportedUncorrectableErrors;
                        break;
                    case 192:
                        m_PropertyName = PropertyNames.PoweroffRetractCount;
                        break;
                    case 193:
                        m_PropertyName = PropertyNames.LoadCycleCount;
                        break;
                    case 194:
                        m_PropertyName = PropertyNames.Temperature;
                        break;
                    case 196:
                        m_PropertyName = PropertyNames.ReallocationEventCount;
                        break;
                    case 197:
                        m_PropertyName = PropertyNames.CurrentPendingSectorCount;
                        break;
                    case 198:
                        m_PropertyName = PropertyNames.OfflineScanUncorrectableSectorCount;
                        break;
                    case 199:
                        m_PropertyName = PropertyNames.UltraDMACRCErrorCount;
                        break;
                    case 201:
                        m_PropertyName = PropertyNames.SoftReadErrorRate;
                        break;
                    case 220:
                        m_PropertyName = PropertyNames.DiskShift;
                        break;
                    case 230:
                        m_PropertyName = PropertyNames.LifeCurveStatus;
                        break;
                    case 232:
                        m_PropertyName = PropertyNames.AvailableReservedSpace;
                        break;
                    case 234:
                        m_PropertyName = PropertyNames.Reserved;
                        break;
                    case 241:
                        m_PropertyName = PropertyNames.LifetimeWritesFromHost;
                        break;
                    case 242:
                        m_PropertyName = PropertyNames.LifetimeReadsFromHost;
                        break;
                }
            }
        }
 
        private string m_PropertyName;
        public string PropertyName
        {
            get { return m_PropertyName; }
        }
 
        public string Value { get; set; }
        public bool IsOk { get; set; }
 
        private struct PropertyNames
        {
            public const string RawReadErrorRate = "Raw Read Error Rate";
            public const string ThroughputPerformance = "Throughput Performance";
            public const string SpinUpTime = "Spin Up Time";
            public const string StartStopCount = "Start/Stop Count";
            public const string ReallocatedSectorCount = "Reallocated Sector Count";
            public const string ReadChannelMargin = "Read Channel Margin";
            public const string SeekErrorRate = "Seek Error Rate";
            public const string SeekTimePerformance = "Seek Time Performance";
            public const string PowerOnHours = "Power-On Hours";
            public const string SpinRetryCount = "Spin Retry Count";
            public const string CalibrationRetryCount = "Calibration Retry Count";
            public const string PowerCycleCount = "Power Cycle Count";
            public const string ProgramFailBlockCount = "Program Fail Block Count";
            public const string EraseFailBlockCount = "Erase Fail Block Count";
            public const string UnknownAttribute = "Unknown Attribute";
            public const string UnexpectedPowerLossCount = "Unexpected Power Loss Count";
            public const string ReportedUncorrectableErrors = "Reported Uncorrectable Errors";
            public const string PoweroffRetractCount = "Power-off Retract Count";
            public const string LoadCycleCount = "Load Cycle Count";
            public const string Temperature = "Temperature";
            public const string ReallocationEventCount = "Reallocation Event Count";
            public const string CurrentPendingSectorCount = "Current Pending Sector Count";
            public const string OfflineScanUncorrectableSectorCount = "Off-line Scan Uncorrectable Sector Count";
            public const string UltraDMACRCErrorCount = "Ultra DMA CRC Error Count";
            public const string SoftReadErrorRate = "Soft Read Error Rate";
            public const string DiskShift = "Disk Shift";
            public const string LifeCurveStatus = "Life Curve Status";
            public const string AvailableReservedSpace = "Available Reserved Space";
            public const string Reserved = "Reserved";
            public const string LifetimeWritesFromHost = "Lifetime Writes From Host";
            public const string LifetimeReadsFromHost = "Lifetime Reads From Host";
        }
    }
}


J'ai volontairement créer une méthode ToString afin de pouvoir deboguer le rendu :

SmartInfos infos = new Smart.Infos();
MessageBox.Show(Convert.ToString(infos));

PS : Je me suis inspiré de ce billet pour obtenir les données de retour :
SMART

Bon codage à tous.

Aucun commentaire:

Enregistrer un commentaire