使用S.M.A.R.T和WMI加载/卸载循环计数

时间:2012-03-24 15:39:27

标签: c# windows-7 wmi disk-smart

在尝试开发硬盘分析工具时,我试图从我的硬盘的S.M.A.R.T数据中获取加载/卸载循环计数的值,我想知道是否有人知道如何执行此操作。 我在尝试什么:

  1. 我正在搜索WMI MSStorageDriver_ATAPISmartData类数据,其中属性编号193是我需要的(表示加载/卸载周期数的属性)
  2. 我得到的数据似乎是
  3. enter image description here

    我认为我很接近,红色的数据与我在运行它时显示的Everest Home版本相同,理想情况下我希望最后一部分是(属性称为数据)

    enter image description here

    收集此数据的方法:

    static void doStuff()
    {
        try
        {
    
            byte TEMPERATURE_ATTRIBUTE = 193;
    
            ManagementObjectSearcher searcher = new ManagementObjectSearcher(@"\root\WMI", "SELECT * FROM MSStorageDriver_ATAPISmartData");
            //loop through all the hard disks
            foreach (ManagementObject queryObj in searcher.Get())
            {
                byte[] arrVendorSpecific = (byte[])queryObj.GetPropertyValue("VendorSpecific");
    
                int tempIndex = Array.IndexOf(arrVendorSpecific, TEMPERATURE_ATTRIBUTE);
                Console.WriteLine("HDD TEMP: " + arrVendorSpecific[tempIndex + 5].ToString());
    
                foreach (byte dat in arrVendorSpecific)
                {
                    Console.Write(dat.ToString() + " ");
                }
            }
    
        }
        catch (Exception err) { Console.WriteLine(err.Message); }
    }
    

    P.S。这个方法适用于收集硬盘的温度(这就是Console.WriteLine("HDD TEMP: " + arrVendorSpecific[tempIndex + 5].ToString());线的全部内容,但我不确定为什么它的tempIndex + 5

1 个答案:

答案 0 :(得分:9)

您使用的代码不正确,因为您正在使用secuencial搜索(Array.IndexOf)来查找SMART Attribute ID(您可能有误报,因为该值可以与数组中的另一个匹配),这些属性的ID在文档结构(SMART Attribute Overview)内部具有固定位置。

SMART属性表

Offset  Length  Description
        (bytes) 
0         2      SMART structure version (this is vendor-specific)
2         12     Attribute entry 1
2+(12)    12     Attribute entry 2
. . .
2+(12*29) 12     Attribute entry 30

在属性表中输入

enter image description here

从这里开始,您可以编写代码来搜索每个属性的位置并获取您要查找的值

using System;
using System.Collections.Generic;
using System.Management;
using System.Text;
using System.Runtime.InteropServices;

namespace GetWMI_Info
{
    class Program
    {

        [StructLayout(LayoutKind.Sequential)]
        public struct Attribute
        {
            public byte AttributeID;
            public ushort Flags;
            public byte Value;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
            public byte[] VendorData;
        }

        static void Main(string[] args)
        {
            try
            {
                Attribute AtributeInfo;
                ManagementScope Scope = new ManagementScope(String.Format("\\\\{0}\\root\\WMI", "localhost"), null);
                Scope.Connect();
                ObjectQuery Query = new ObjectQuery("SELECT VendorSpecific FROM MSStorageDriver_ATAPISmartData");
                ManagementObjectSearcher Searcher = new ManagementObjectSearcher(Scope, Query);
                byte LoadCycleCount = 0xC1;
                int Delta  = 12;
                foreach (ManagementObject WmiObject in Searcher.Get())
                {
                    byte[] VendorSpecific = (byte[])WmiObject["VendorSpecific"];
                    for (int offset = 2; offset < VendorSpecific.Length; )
                    {
                        if (VendorSpecific[offset] == LoadCycleCount)
                        {

                            IntPtr buffer = IntPtr.Zero;
                            try
                            {
                                buffer = Marshal.AllocHGlobal(Delta);
                                Marshal.Copy(VendorSpecific, offset, buffer, Delta);
                                AtributeInfo = (Attribute)Marshal.PtrToStructure(buffer, typeof(Attribute));
                                Console.WriteLine("AttributeID {0}", AtributeInfo.AttributeID);
                                Console.WriteLine("Flags {0}", AtributeInfo.Flags);
                                Console.WriteLine("Value {0}", AtributeInfo.Value);
                                Console.WriteLine("Value {0}", BitConverter.ToString(AtributeInfo.VendorData));
                            }
                            finally
                            {
                                if (buffer != IntPtr.Zero)
                                {
                                    Marshal.FreeHGlobal(buffer);
                                }
                            }                                                
                        }
                        offset += Delta;
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(String.Format("Exception {0} Trace {1}",e.Message,e.StackTrace));
            }
            Console.WriteLine("Press Enter to exit");
            Console.Read();
        }
    }
}