使用S.M.A.R.进行负载/卸载循环计数。T和WMI

时间:2021-07-26 02:13:36

In an attempt to develop a hard disk analytic tool, I'm trying to get the value of Load/Unload cycle count from my hard disk's S.M.A.R.T data, I'm wondering if anyone knows how to do this. What I'm trying:

为了开发一个硬盘分析工具,我正在尝试从硬盘的s.m.a.r中获得加载/卸载周期数的值。T数据,我想知道有没有人知道怎么做。我尝试:

  1. I'm searching the WMI MSStorageDriver_ATAPISmartData class data where attribute number 193 is what i need (the attribute representing load/unload cycle count)
  2. 我正在搜索WMI MSStorageDriver_ATAPISmartData类数据,其中第193个属性是我需要的(表示负载/卸载周期计数的属性)
  3. The data I'm getting looks like
  4. 我得到的数据是这样的。

使用S.M.A.R.进行负载/卸载循环计数。T和WMI

I think I'm close, the data in red is the same as what Everest Home edition is showing when i run it, ideally i would want the last part which is (attribute called data)

我想我已经很接近了,红色的数据和我运行的珠穆朗玛峰是一样的,理想情况下,我想要的是最后一部分(属性称为数据)

使用S.M.A.R.进行负载/卸载循环计数。T和WMI

Method for collecting this data:

收集数据的方法:

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. this method works for collecting the HDD's temperature (that's what the Console.WriteLine("HDD TEMP: " + arrVendorSpecific[tempIndex + 5].ToString()); line is all about but I'm not sure why its tempIndex+5

这个方法用于收集HDD的温度(控制台就是这样)。WriteLine(“HDD TEMP:”+ arrVendorSpecific[tempIndex + 5].ToString());线是关于,但我不确定为什么它的tempIndex+5。

1 个解决方案

#1


8  

The code which you are using is not correct, because you are using a secuencial search (Array.IndexOf) to find the S.M.A.R.T Attribute ID (you can have false positives because that value can match with another in the array), the ID of these attibutes has an fixed position inside of an documented structure (SMART Attribute Overview).

您使用的代码是不正确的,因为您正在使用secuencial search (Array.IndexOf)来查找S.M.A.R.。T属性ID(你可以有假阳性,因为这个值可以与数组中的另一个值匹配),这些attibutes的ID在一个文档结构的内部有一个固定的位置(SMART属性概述)。

SMART Attribute Table

聪明的属性表

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

Entry in the Attribute Table

属性表中的条目。

使用S.M.A.R.进行负载/卸载循环计数。T和WMI

from here you can write a code to search the location of each attribute and get the values which you are looking for

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

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

#1


8  

The code which you are using is not correct, because you are using a secuencial search (Array.IndexOf) to find the S.M.A.R.T Attribute ID (you can have false positives because that value can match with another in the array), the ID of these attibutes has an fixed position inside of an documented structure (SMART Attribute Overview).

您使用的代码是不正确的,因为您正在使用secuencial search (Array.IndexOf)来查找S.M.A.R.。T属性ID(你可以有假阳性,因为这个值可以与数组中的另一个值匹配),这些attibutes的ID在一个文档结构的内部有一个固定的位置(SMART属性概述)。

SMART Attribute Table

聪明的属性表

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

Entry in the Attribute Table

属性表中的条目。

使用S.M.A.R.进行负载/卸载循环计数。T和WMI

from here you can write a code to search the location of each attribute and get the values which you are looking for

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

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