2013-02-04 3 views
6

내가 만드는 코드를 찾고 있어요 사용할 수있는 HDD의 SMART는을 이상적으로 다음과 같은 또는 유사한 형식으로, WMI (또는 다른 사용) 등록 임계 값, 데이터 (공급 업체) 및 SMART 상태.C# WMI HDD SMART

지금까지 발견 한 많은 WMI 구현은 임계 값을 제공하지 않거나 하나 이상의 표준 SMART 필드 (예 : 현재, 최악, 임계 값)가 누락되었습니다.

+0

http://stackoverflow.com/questions/9352017/smart-hard-drive-data-in-c-sharp – t3hn00b

+0

행운을 빕니다, 나는 Stackoverflow.com에서 찾은 모든 "C# HDD SMART"솔루션을 테스트했습니다. – TheLegendaryCopyCoder

답변

13

일부 작업을 마친 후 C#/WMI를 사용하여 HDD에 관련된 모든 SMART 정보에 대한 포괄적 인 보고서를 반환하는 코드를 작성했습니다.

here에서 도출으로

,이 코드입니다 :

/* 
Copyright (c) 2013, Llewellyn Kruger 
All rights reserved. 
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
*/ 
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")}, 
       /* slot in any new codes you find in here */ 
      }; 

    } 

    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; 
    } 
    } 

    /// <summary> 
    /// Tested against Crystal Disk Info 5.3.1 and HD Tune Pro 3.5 on 15 Feb 2013. 
    /// Findings; I do not trust the individual smart register "OK" status reported back frm the drives. 
    /// I have tested faulty drives and they return an OK status on nearly all applications except HD Tune. 
    /// After further research I see HD Tune is checking specific attribute values against their thresholds 
    /// and and making a determination of their own (which is good) for whether the disk is in good condition or not. 
    /// I recommend whoever uses this code to do the same. For example --> 
    /// "Reallocated sector count" - the general threshold is 36, but even if 1 sector is reallocated I want to know about it and it should be flagged. 
    /// </summary> 
    public class Program 
    { 
    public static void Main() 
    { 
     try 
     {   

      // retrieve list of drives on computer (this will return both HDD's and CDROM's and Virtual CDROM's)      
      var dicDrives = new Dictionary<int, HDD>(); 

      var wdSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive"); 

      // extract model and interface information 
      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");   

      // retrieve hdd serial number 
      iDriveIndex = 0; 
      foreach (ManagementObject drive in pmsearcher.Get()) 
      { 
      // because all physical media will be returned we need to exit 
      // after the hard drives serial info is extracted 
      if (iDriveIndex >= dicDrives.Count) 
       break; 

      dicDrives[iDriveIndex].Serial = drive["SerialNumber"] == null ? "None" : drive["SerialNumber"].ToString().Trim();     
      iDriveIndex++; 
      } 

      // get wmi access to hdd 
      var searcher = new ManagementObjectSearcher("Select * from Win32_DiskDrive"); 
      searcher.Scope = new ManagementScope(@"\root\wmi");  

      // check if SMART reports the drive is failing 
      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++; 
      } 

      // retrive attribute flags, value worste and vendor data information 
      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]; // least significant status byte, +3 most significant byte, but not used so ignored. 
        //bool advisory = (flags & 0x1) == 0x0; 
        bool failureImminent = (flags & 0x1) == 0x1; 
        //bool onlineDataCollection = (flags & 0x2) == 0x2; 

        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 
       { 
        // given key does not exist in attribute collection (attribute not in the dictionary of attributes) 
       }     
       } 
       iDriveIndex++; 
      } 

      // retreive threshold values foreach attribute 
      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 
       { 
       // given key does not exist in attribute collection (attribute not in the dictionary of attributes) 
       } 
      } 

      iDriveIndex++; 
      } 


     // print 
     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); 
     } 
    } 
    } 

업데이트 - 2017년 12월 19일

내가 함께 모든 스마트 데이터를 쿼리 단순화하는 클래스 라이브러리를 넣었습니다 당신은 필요합니다. 데모 프로젝트가 포함되어 있습니다.

GitHub의 환매 약정 :Smart.Net Library

사용법 : 어쩌면

var drives = Simplified.IO.Smart.GetDrives(); // Static Method 
+1

다음 두 가지 이유로 귀하의 웹 사이트/제품에 대한 베어 링크가 권장되지 않습니다. 첫째, 답변은 외부 사이트에 대한 단순한 링크가 아닌 자체 포함 답변으로 게시해야합니다. 둘째, 자기 홍보는 여기에서 눈살을 찌푸리게되는 경향이 있으며, 종종 스팸으로 신고됩니다 (특히 자신의 사이트/제품에 연결한다는 공개가없는 경우). –

+9

안녕하세요 앤드류, 지금은 지금 응답 할 시간이있었습니다. stackoverflow에서 찾고 나는 단순히 링크입니다 답변을 많이 참조하십시오. 나는이 경우에 똑같은 일을했고 그 문제를 보지 못했습니다. 둘째, 자기 홍보에 대한 귀하의 의견과 관련하여; 나는 다른 사람들이 눈살을 찌푸린 것에 대해 아무런 말도하지 않는다. 사실, 아무도 내 질문에 대한 해결책을 제공하지 못했습니다. 나는 시간과 돈을 함께 풀어 세상과 공유했다. 영향을 stackoverflow groupies 스위트를 따르도록하고 아래로 좋은 대답을 투표. 아무도 이기지 않습니다. – TheLegendaryCopyCoder

+0

더 이상 블로그에 링크되어 있지 않으므로이 코드와 관련하여 해당 링크에는 정보가 없습니다. 스택 오버플로가 한 줄의 링크가없는 대답을 선호하는 이유입니다. – VampyreSix