WMI 获取硬盘信息(使用时间)

Get Smart

Now that we have the basics of WMI in .NET worked out it's time to get back to SMART. Some information presented by WMI is provided by SMART and this is fairly easy to get at. For example, if you simply want to discover what SMART thinks of each drive you can make use of the WMI Win32_DiskDrive object and its Status property. This gives an overall disk status based on SMART and other considerations. The possible values are:

OK, Error, Degraded, Unknown, Pred Fail, Starting, Stopping, Service, Stressed, NonRecover, No Contact, Lost Comm

Pred Fail, i.e. Predicted Failure result, is the one that we are most interested in using as a way of avoiding trouble before it happens. Start a new project and place a button labelled “Get Drive Status” on the form along with a RichTextBox. To read the Status property and present it enter the following into the button’s click event handler :

private void button1_Click(
object sender,EventArgs e)
{
ManagementObjectSearcher WMISearch =
new ManagementObjectSearcher(
"Select * from Win32_DiskDrive");
ManagementObjectCollection Drives =
WMISearch.Get();
richTextBox1.Text =
"Drive/t/t/tStatus/n";
foreach ( ManagementObject Drive
in Drives )
{
richTextBox1.Text = richTextBox1.Text +
Drive.Properties["DeviceId"].
Value.ToString()+"/t";
richTextBox1.Text = richTextBox1.Text +
Drive.Properties["Status"].
Value.ToString()+"/n";
}
}

The “/t”s are tab formatting characters and the “/n” is a newline.

If you want to go beyond this simple go/no-go test then there are a number of problems. There are four WMI objects that provide access to SMART but lack of documentation makes them difficult to use. The only information available can be found in an archived paper on the Micorosft site which describes four objects:

MSStorageDriver_FailurePredictStatus
MSStorageDriver_FailurePredictData
MSStorageDriver_FailurePredictEvent
MSStorageDriver_FailurePredictFunction

The first provides information on the state of the drive similar to the state property already described. The second provides the SMART data that this decision was based on but the format used varies according to the make of the drive and no information is given how to decipher it. The third implements events based on the SMART status and the fourth provides methods that can be used to configure a SMART drive and initiate a test.

To get at the SMART data we need to use MSStorageDriver_FailurePredictData. This is stored in /root/wmi rather than the default /root/cimv2 and means we need to set the scope:

WMISearch.Scope=new 
ManagementScope(@"/root/wmi" );

You can also specify a machine and user if you want to collect data on a remote machine. The WQL query is:

WMISearch.Query=new ObjectQuery(
"Select * from
MSStorageDriver_FailurePredictData");
ManagementObjectCollection
FailDataSet = WMISearch.Get();

The FailDataSet contains a block of SMART data for each drive in the system that supports it. Each of the FailData objects in the collection has a VendorSpecific property which returns a byte array full of SMART data.

The big problem is in figuring out what it all means as it really is “vendor specific”. The data is organised into 12 byte blocks of attribute data. The first byte of the array gives the number of attribute blocks. Each attribute block has the format:

Item    Data
0 and 1 Unknown usually zero
2 Attribute
3 Status
4 Unknown usually zero
5 Value
6 Worst
7,8 Raw Value
9,10,11 Unknown usually zero

The attribute codes are also not standardised but there are a core set that you can rely on:

Code  Attribute
1       Raw Read Error Rate
2 Throughput Performance
3 Spin Up Time
4 Start/Stop Count
5 Reallocated Sector Count
6 Read Channel Margin
7 Seek Error Rate
8 Seek Time Performance
9 Power On Hours Count
10 Spin Retry Count
11 Calibration Retry Count
12 Power Cycle Count
192 Power-off Retract Count
193 Load Cycle Count
194 Temperature
196 Reallocation Event Count
197 Current Pending Sector Count
198 Off-line Scan Uncorrectable Sector Count
199 Ultra DMA CRC Error Count
201 Soft Read Error Rate
220 Disk Shift

Not all drives support all attributes and you can be certain that some will report attributes not in this list. To get and decode the data returned by WMI we need another RichTextBox and some appropriate headings:

richTextBox2.Text = 
"Unknw/tUnknw/tAttribute
/tStatus/tUnknw/tValue/
tWorst/tRaw/t/tUnknw/n";

Now to display each set of FailData we need a foreach loop:

foreach ( ManagementObject FailData in
FailDataSet )
{

The data is returned as an object type but we know it’s really a byte array and the simplest way of working with it is to retrieve it and cast it to a byte array:

Byte[] data = (Byte[])FailData.
Properties["VendorSpecific"].Value;

Finally we can add each attribute to the RichTextBox making use of the fact that each block of 12 bytes corresponds to an attribute:

for (int i = 0; i < data[0]-1; i++)
{
for (int j = 0; j < 12; j++)
{
richTextBox2.Text = richTextBox2.Text
+ data[i*12+j] + "/t";
}
richTextBox2.Text = richTextBox2.Text + "/n";
}

If you now run the program you will see the raw SMART data displayed as a table. Your next task is to process it and build it into a useful reporting tool that will warn you if anything is going wrong.

smart

The raw SMART data

If you want to work with the data in a more object-oriented way then you probably need to create a SMART class but a SMART struct also works well. For example, a struct that holds values for the most important failure indicators would be:

public struct SMARTAttribute
{
public int status;
public int value;
public int rawvalue;
}
public struct SMART
{
public SMARTAttribute
RawReadErrorRate;
public SMARTAttribute
ReallocatedSectorCount;
public SMARTAttribute
ReallocationEventCount;
public SMARTAttribute
CurrentPendingSectorCount;
public SMARTAttribute
OfflineScanUncorrectableSectorCount;
}

Packing the data into the struct is just a matter of detecting which attribute the current 12 bytes of data represents and the best way to do this is with a switch:

SMART smartdata;
foreach (ManagementObject FailData2 in
FailDataSet)
{
Byte[] data2 = (Byte[])FailData2.
Properties["VendorSpecific"].Value;
for (int i = 0; i < data2[0] - 1; i++)
{
int start=i*12;
switch(data2[start+2])
{
case 1:
smartdata.RawReadErrorRate.value =
data2[start + 5];
smartdata.RawReadErrorRate.rawvalue=
data2[start+7]+256*data2[start+8];
break;
case 5:
smartdata.ReallocatedSectorCount.
value =data2[start + 5];
smartdata.ReallocatedSectorCount.
rawvalue = data2[start + 7]
+ 256 * data2[start + 8];
break;
case 196:
smartdata.ReallocationEventCount.
value =data2[start + 5];
smartdata.ReallocationEventCount.
rawvalue =data2[start + 7]
+ 256 * data2[start + 8];
break;
case 197:
smartdata.CurrentPendingSectorCount.
value = data2[start + 5];
smartdata.CurrentPendingSectorCount.
rawvalue = data2[start + 7]
+ 256 * data2[start + 8];
break;
case 198:
smartdata.
OfflineScanUncorrectableSectorCount.
value = data2[start + 5];
smartdata.
OfflineScanUncorrectableSectorCount.
rawvalue = data2[start + 7]
+ 256 * data2[start + 8];
break;
}
}

You can add extra code to initialise the other data values and retrieve other attributes if you need them. Once you have seen how it’s done it’s not so difficult.

It is also possible to run such WMI queries remotely once you have worked out how to set the system up to allow it. See Getting remote DCOM (WMI) to work.

If you would like the code for this article register with I Programmer and click visit the codebin.

//X前面的网页居然打不开了,明天在试下

http://www.i-programmer.info/projects/38-windows/208-disk-drive-dangers.html?start=2

http://social.msdn.microsoft.com/Forums/id-ID/1761/thread/d571e125-c5e6-4aa7-b7b3-0440a784906b

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值