Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.96/26: Рейтинг темы: голосов - 26, средняя оценка - 4.96
NamelessOne
0 / 0 / 0
Регистрация: 17.02.2014
Сообщений: 9
1

Атрибуты SMART через запрос WMI на языке C#

17.02.2014, 20:27. Просмотров 4682. Ответов 6
Метки нет (Все метки)

Здравствуйте, передо мной возникла задача: написание программы, которая оценивает техническое состояние жёсткого диска. Я выяснил, что это можно сделать с помощью технологии S.M.A.R.T.
Здесь: Расшифровка параметров S.M.A.R.T, я прочитал о параметрах S.M.A.R.T.
При дальнейшем изучении вопроса стало понятно, что мне проще и удобнее всего получить доступ к параметрам S.M.A.R.T. с помощью технологии Windows Management Instrumentation (WMI), запросом на специальном языке WQL. В сети я нашёл статью, в которой описывается получение атрибутов S.M.A.R.T.:
http://www.i-programmer.info/projects/38/208.html?start=1
То есть параметры S.M.A.R.T. содержатся в структуре данных VendorSpecific, фактически являющейся массивом из байтов.
Вот код, приведённый там:
[
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ManagementObjectSearcher WMISearch = new ManagementObjectSearcher();
WMISearch.Scope = new ManagementScope(@"\root\wmi");
WMISearch.Query = new ObjectQuery("Select * from MSStorageDriver_FailurePredictData");
ManagementObjectCollection FailDataSet = WMISearch.Get();
richTextBox1.Text = "Unknw\tUnknw\tAttribute\tStatus\tUnknw\tValue\tWorst\tRaw\t\tUnknw\n";
foreach ( ManagementObject FailData in FailDataSet )
{
    Byte[] data = (Byte[])FailData.Properties["VendorSpecific"].Value;
    for (int i = 0; i < data[0]-1; i++)
    {
        for (int j = 0; j < 12; j++)
        {
            richTextBox1.Text += data[i*12+j] + "\t";
        }
        richTextBox1.Text += "\n";
    }
}
Вот то, что вывела программа в моём случае:
Un___Un___ID___(?)___Un___Vale_Wrst Raw Unknw
10___0____1____15___0____100__253__0____0____0____0____0
0____0____3____3____0____99___99___0____0____0____0____0
0____0____4____50___0____98___98___64___10___0____0____0
0____0____5____51___0____100__100__0____0____0____0____0
0____0____7____15___0____87___60___229__122__192__28___1
0____0____9____50___0____94___94___151__21___0____0____0
0____0____10___19___0____100__100__0____0____0____0____0
0____0____12___50___0____98___98___66___10___0____0____0
0____0____187__50___0____100__100__0____0____0____0____0

Таким образом, программа вывела почти все значения атрибутов: ID, Value, Worst, и RAW, кроме Threshold. И ещё загадочный Status (?).
Вопрос: где взять Threshold, ведь он очень важен - позволяет оценить состояние атрибута.
Поле Status им точно не является, т.к. это значение не совпадает с тем, которое вывела другая программа SpeedFun.
Буду очень благодарен за помощь в поисках этого Threshold.
0
Лучшие ответы (1)
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
17.02.2014, 20:27
Ответы с готовыми решениями:

[C#+WMI]Можно ли через WMI узнать температуру процессора и ядер?
Можно ли через WMI узнать температуру процессора и ядер? Щас лопачу сайты вожусь но русскоязычной...

Удалённый доступ WMI на языке C#
Здравствуйте, у меня такой вопрос. Как правильно реализовать удалённый доступ WMI на C#?...

Какие существуют атрибуты переменной в языке ассемблера (MASM/TASM) для процессора Intel x86
Какие Атрибуты имеет переменная на языке ассемблера(MASM/TASM) для МП INTEL x86? (И где об этом...

WMI Запрос для класса Win32_NetworkAdapterConfiguration с фильтрацией IPv6
Добрый день Использую BGINFO для отображение имени пользователя\пк и тп и тд. Вопрос, для...

Поставщик HiPerfCooker_v1 зарегистрирован в пространстве имен WMI Root\WMI с правами локальной системы
Поставщик HiPerfCooker_v1 зарегистрирован в пространстве имен WMI Root\WMI с правами локальной...

6
Psilon
Master of Orion
Эксперт .NET
6041 / 4899 / 903
Регистрация: 10.07.2011
Сообщений: 14,515
Записей в блоге: 5
Завершенные тесты: 4
17.02.2014, 20:34 2
NamelessOne, скачайте какую-нибудь стороннюю утилиту (например, PerfectDisk, у него есть триальный период), ну или какой-нибудь бесплатный CrystalDiskInfo, и сравните те значения с этими. Может поле Unknown это то, что вы ищете.
0
NamelessOne
0 / 0 / 0
Регистрация: 17.02.2014
Сообщений: 9
17.02.2014, 20:36  [ТС] 3
Я уже сравнивал их, ничего общего, кроме тех, о которых я упоминал.
0
Psilon
Master of Orion
Эксперт .NET
6041 / 4899 / 903
Регистрация: 10.07.2011
Сообщений: 14,515
Записей в блоге: 5
Завершенные тесты: 4
17.02.2014, 20:51 4
NamelessOne, ну почему сразу ничего общего:
0
Миниатюры
Атрибуты SMART через запрос WMI на языке C#  
NamelessOne
0 / 0 / 0
Регистрация: 17.02.2014
Сообщений: 9
17.02.2014, 21:06  [ТС] 5
Вывела моя программа:
Un___Un___ID___(?)___Un___Vale_Wrst Raw Unknw
10___0____1____15___0____100__253__0____0____0____0____0
Вывела программа SpeedFun:
ID: 1
Value: 100
Worst: 253
Warn: 6 (Treshold)
Raw: 0
Как видите, числа 6 в моей программе нет.
0
Psilon
Master of Orion
Эксперт .NET
6041 / 4899 / 903
Регистрация: 10.07.2011
Сообщений: 14,515
Записей в блоге: 5
Завершенные тесты: 4
17.02.2014, 21:11 6
Лучший ответ Сообщение было отмечено Psilon как решение

Решение

NamelessOne, нагуглил вот такой код, Если честно, лень разбираться после рабочего дня, попробуйте его, работает вроде неплохо, ну а в коде, думаю, разберетесь:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
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);
        }
    }
}
1
NamelessOne
0 / 0 / 0
Регистрация: 17.02.2014
Сообщений: 9
17.02.2014, 21:21  [ТС] 7
Действительно, выводит все интересующие меня параметры. Буду разбираться.
Большое спасибо за помощь!
0
17.02.2014, 21:21
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
17.02.2014, 21:21

Запрос выводит не все атрибуты таблицы
Здравствуйте, ниже запрос select на вывод атрибутов из бд и проблема в том что выводит только...

Подключение к удаленному компьютеру через WMI
вот код, который использую: ConnectionOptions options = new ConnectionOptions(); ...

Как управлять службами Windows через WMI?
Помогите написать Windows-форму (проект Windows Form Application), которая выводит список всех...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.