S.M.A.R.T情報をWMIでSSDから取得する

プログラミング
Sponsored links
Sponsored links

はじめに

SSDの寿命は世代が変わるごとに短くなっているとの情報を耳にしたことから、SSDの寿命に関して気になりだしました。
SSDの寿命を測定するにはSSDのS.M.A.R.T情報から推測するしか方法はなさそうです。
S.M.A.R.T情報を確認するには定番のフリーソフトCristal DiskInfoを使えばよいのですが、会社のPCに勝手にソフトウェアをインストールすることができません。
仕方がないので、S.M.A.R.T情報を取得するソフトウェアを作成してみることにしました。

データを取得する

S.M.A.R.T情報は、各メーカーまた製品に依存しています。
Cristal DiskInfoなどは、ある程度の製品情報を持っているようなので、情報の意味がよくわかるようになっています。
しかし、我が社のPCのSSDは多種多様で、また、Cristal DiskInfoでは項目名が出てこないものが結構ありました。
調べてみると、わざわざ産業用のSSDに載せ替えているものがあるようです。
そのため、S.M.A.R.Tの生データを取得することにしました。
とりあえず生データを仕様書と照らし合わせて解析するつもりです。
仕様書が手に入るかどうかわかりませんが…

開発環境

Visual Studio 2010 C#
WMI(Windows Management Instrumentation)を使ってS.M.A.R.T情報を取得します。

ソースコード

SSDのドライブ情報を取得する

using System.Management;

static void Main(String[] args)
{
 	// ディスクドライブ情報
    InfoData infoDisk = new InfoData() { Name = "Disk", WimClass = "Win32_DiskDrive", WimValue = "Caption", format = "{0}" };
	GetWmiData(ref infoDisk);
	infoDisk.Value = String.Format("{0}", (string)infoDisk.oValue);
}

static private void GetWmiData(ref InfoData c)
{
	String sql = "SELECT * FROM " + c.WimClass;
	ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", sql);
	foreach (ManagementObject queryObj in searcher.Get())
	{
		c.oValue = queryObj[c.WimValue];
	}
}

class InfoData
{
	public String Name { get; set; }
	public String WimClass { get; set; }
	public String WimValue { get; set; }
	public String format { get; set; }

	public object oValue{get;set;}
	public String Value { get; set; }
}

S.M.A.R.T情報を取得する

static void Main()
{
 SmartData smart;
 GetSmart(out smart);
 foreach (SmartStruct ss in smart.smart)
 {
	String smart_data = String.Format("{0},{1},{2},{3},{4},",ss.AttrId,ss.Status1,ss.Status2,ss.value,ss.worst);
	for (int i = 0; i < 6; ++i)
	{
		smart_data += String.Format("{0},", ss.Raw[i]);
	}
	smart_data += String.Format("{0}", ss.reserved);
	lines.Add(smart_data);
 }

 File.WriteAllLines(@"C:\SMART.csv", lines, Encoding.GetEncoding("shift-jis"));
}

static private void GetSmart(out SmartData smart)
{
	Byte[] arrVendorSpecific = null;
	ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\WMI", "SELECT * FROM MSStorageDriver_FailurePredictData");
	foreach (ManagementObject queryObj in searcher.Get())
	{
		arrVendorSpecific = (Byte[])(queryObj["VendorSpecific"]);
	}
	smart= new SmartData();
	int cnt = smart.set(arrVendorSpecific);
}

class SmartData
{
	public List<SmartStruct> smart = new List<SmartStruct>();

	public int set(Byte[] data)
	{
		int cnt = 0;
		int shift = 2;
		do
		{
			SmartStruct s = new SmartStruct();
			shift = s.Set(ref data, shift);
			if (shift == 0)
				break;
			smart.Add(s);
			++cnt;
		} while (0 < shift && shift < 361);

		return cnt;
	}
}

class SmartStruct
{
	public Byte AttrId;
	public Byte Status1;
	public Byte Status2;
	public Byte value;
	public Byte worst;
	public Byte[] Raw = new Byte[6];
	public Byte reserved;

	public int Set(ref Byte[] data, int shift)
	{
		try
		{
			AttrId = data[shift++];
			if (AttrId == 0)
			{
				shift = 0;
				return shift;
			}
			Status1 = data[shift++];
			Status2 = data[shift++];
			value = data[shift++];
			worst = data[shift++];
			Raw[0] = data[shift++];
			Raw[1] = data[shift++];
			Raw[2] = data[shift++];
			Raw[3] = data[shift++];
			Raw[4] = data[shift++];
			Raw[5] = data[shift++];

			reserved = data[shift++];

		}
		catch (Exception)
{
			shift = 0;
		}

		return shift;
	}
}

最後に

今回はデータを取得するためだけだったので、コンソールアプリケーションで簡単に作成しました。データの解析をするためには、各SSDのS.M.A.R.T仕様を調べなければなりません。さて、調べられるでしょうか?

タイトルとURLをコピーしました