5

Just trying to pull off some SMART info from connected Hard Drives on any computer my application will run on.

I'm using WMI for a lot of other stuff in the program, and every question about SMART I've looked at makes reference to Win32_DiskDrive. However, the data in here is really quite minimal and probably not SMART - I'm searching for information such as 'Spin Retry Count'. Any ideas?

Mat
  • 202,337
  • 40
  • 393
  • 406
Chris Watts
  • 6,197
  • 7
  • 49
  • 98
  • Here is the answer: http://blogs.msdn.com/b/clemensv/archive/2011/04/11/reading-atapi-smart-data-from-drives-using-net-temperature-anyone.aspx – Kamil Feb 19 '12 at 18:47
  • You searching in wrong class. Find MSStorageDriver_ATAPISmartData class and read from it. Google MSStorageDriver_ATAPISmartData for more information. – Kamil Feb 19 '12 at 20:31
  • @CJxD you need to access the MSStorageDriver_ATAPISmartData class, select it's deta, map the correct bytes to the correct structures (bytes, ushorts, ints etc.) – Lyuben Todorov Mar 26 '12 at 19:17

1 Answers1

6

You are using the wrong class (you want MSStorageDriver_ATAPISmartData). To change what attribute you want change byte SpinRetryCount = 0x0A; to whatever value you wish (e.g. 0x02 for throughput performance)

[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 getSMARTAttr()
        {
            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 SpinRetryCount = 0x0A;
                int Delta = 12;
                foreach (ManagementObject WmiObject in Searcher.Get())
                {
                    byte[] VendorSpecific = (byte[])WmiObject["VendorSpecific"];
                    for (int offset = 2; offset < VendorSpecific.Length; )
                    {
                        if (VendorSpecific[offset] == SpinRetryCount)
                        {

                            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);
                                //if you want HEX values use this line
                                //Console.WriteLine("Value {0}", BitConverter.ToString(AtributeInfo.VendorData));
                                //if you want INT values use this line
                                Console.WriteLine("Data {0}", BitConverter.ToInt32(AtributeInfo.VendorData, 0));
                            }
                            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();
        }

And remember that if you get anything other than 0, you need to buy a new hard drive! Also this code requires UAC elevation, so you need to run the application as an administrator or you will get an exception.

Lyuben Todorov
  • 13,987
  • 5
  • 50
  • 69