|
Delphi Programming / Object Pascal
[掲載 2008年05月01日] [更新 2015年04月27日] Delphi サンプルプログラム集 |
900_WMI ハードウェア関係情報の取得 |
動作確認等 |
Windows 7 U64(SP1) + Delphi XE(UP1) Pro |
|
900_WMI_HardWare.zip [4,114 KB] 2015年04月27日版 (EXE 同梱) |
- 2010年07月28日
- プロパティ取得のループ処理を While 文を使用するコードに統一し,解説的な内容も考慮
|
- 2013年09月03日
- [898_WMI イントロダクション] の更新に伴い,コードを整備し,記事も整理
|
- 2015年04月27日
- プロセッサ (CPU) の温度取得のサンプルを追加
|
WMI でハードウェア,ソフトウェアの情報,プロパティということになりますが,これらを取得する手順は次のようになります.
- (1) WMI オブジェクトのインスタンスを生成
- (2) そのインスタンスを WMI サービスに接続
- (3) そのサービスに対して,プロパティのセットを取得するクエリーを実行
- (4) クエリーの結果からプロパティを取得していく
1 番目と 2 番目のコードはいつもほとんど同じです.
3 番目のクエリ文で,使用する Win32_LogicalDisk と言ったクラス名と呼ばれる部分を,目的に応じて変えることになります.どのようなクラスに,どのような機能があるかは,[WMI イントロダクション] のページの参考リンクの記事を参考にしてください.その数は膨大です.
本ページでは,主に,Win32 Classes クラスの Computer System Hardware Classes の一部のクラスを使用して,ハードウェアの情報を取得します. |
[備考]
Storage Management API は Windows 8 以降で使用可能です.
[SSD かどうかを WMI から判別する] の記事は,この Storage Management API を使用しています. |
クエリーに Win32_ComputerSystem クラスを指定して,ローカルコンピュータのシステム情報を取得するサンプルです.
Edit1 のテキストにクラス名を入力しています.したがって,この文字列を変更すれば,他のクラスを指定して,その情報を取得することもできるようにしています. |
|
図1
設計時画面 |
|
図2
実行例 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, WbemScripting_TLB, ComCtrls, ExtCtrls, ComObj, ActiveX;
type
TForm1 = class(TForm)
Panel1: TPanel;
Panel2: TPanel;
Button1: TButton;
ListView1: TListView;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private 宣言 }
function VarToString(const OleVar: OleVariant): String;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// フォーム生成時の処理
// クエリの対象となるクラスを設定
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Edit1.Text := 'Win32_ComputerSystem';
end;
//=============================================================================
// 全論理ディスクの情報取得
// 全てのプロパティを取得
// TListViewの各行をプロパティとして表示
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
objWMILocator : ISWbemLocator;
objWMIService : ISWbemServices;
objPropSet : ISWbemObjectSet;
objPropSetEnum : IEnumVariant;
objTemp : OleVariant;
iValue : LongWord;
wmiPropSet : ISWbemPropertySet;
wmiPropSetEnum : IEnumVariant;
wmiProperty : ISWbemProperty;
AColumn : TListColumn;
AItem : TListItem;
RowNo : Integer;
strClassName : String;
begin
strClassName := Trim(Edit1.Text);
//WMIのオブジェクトを生成
objWMILocator := CoSWbemLocator.Create;
//WMIサービスに接続.引数は必要に応じて設定
objWMIService := objWMILocator.ConnectServer(
'',
'root\cimv2',
'',
'',
'',
'',
0,
nil);
//クエリーを実行して,プロパティのセットのオブジェクトを取得
objPropSet := objWMIService.ExecQuery(
'Select * From ' + strClassName,
'WQL',
wbemFlagReturnImmediately,
nil);
//プロパティのセットのコレクションを取得
objPropSetEnum := objPropSet._NewEnum as IEnumVariant;
//-------------------------------------------------------------------------
// 以下がプロパティの取得コード
//-------------------------------------------------------------------------
ListView1.Items.Clear;
ListView1.Items.BeginUpdate;
ListView1.Columns.Clear;
//プロパティ名のカラム作成(左端列)
AColumn := ListView1.Columns.Add;
AColumn.Caption := 'プロパティ';
AColumn.Width := 200;
//プロパティセットの数だけ繰返す
while objPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
//プロパティのセットを取得
wmiPropSet := (IUnknown(objTemp) as ISWBemObject).Properties_;
wmiPropSetEnum := (wmiPropSet._NewEnum) as IEnumVariant;
//プロパティセットごとにカラムを追加
AColumn := ListView1.Columns.Add;
AColumn.Caption := IntToStr(ListView1.Columns.Count - 1);
AColumn.Width := 190;
RowNo := 0;
//プロパティの数だけ繰返す
//プロパティ名はName,プロパティの値はGet_Valueで取得
while wmiPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
if VarIsNull(objTemp) then Continue;
//プロパティを取得
wmiProperty := IUnknown(objTemp) as ISWBemProperty;
//最初のデータ取得の際には行を追加.TListViewのCaptionはプロパティ名
if ListView1.Columns.Count = 2 then begin
AItem := ListView1.Items.Add;
AItem.Caption := VarToString(wmiProperty.Name);
end;
//プロパティの値を表示
AItem := ListView1.Items.Item[RowNo];
AItem.SubItems.Add(VarToString(wmiProperty.Get_Value));
//次の行
RowNo := RowNo + 1;
end;
end;
ListView1.Items.EndUpdate;
end;
//=============================================================================
// OleVariantの値をString型に変換(再帰処理)
// 複数の値を持つプロパティがある.そこでこれを[]で括った結果を返すことにする
// そのためVarArrayも扱えるようにしたVarToStr関数
//=============================================================================
function TForm1.VarToString(const OleVar: OleVariant): String;
var
LowBound : Integer;
HighBound : Integer;
i : Integer;
begin
Result := '';
//配列の場合
if VarIsArray(OleVar) then begin
LowBound := VarArrayLowBound(OleVar, 1);
HighBound := VarArrayHighBound(OleVar, 1);
for i := LowBound to HighBound do begin
if i = HighBound then begin
Result := Result + VarToString(OleVar[i]);
end else begin
Result := Result + VarToString(OleVar[i]) + ',';
end;
end;
Result:='[' + Result + ']';
//単一の値を持つプロパティの場合
end else begin
Result := VarToStr(OleVar);
end;
if Result = '' then Result := 'NULL';
end;
end.
クエリーに Win32_LogicalDisk クラスを指定して,システムの全論理ディスクの全プロパティを取得して表示します.[WMI イントロダクション] でも扱いましたが,このサンプルでは,TListView に結果を表示します.TListView の各項目のタイトル (第 1 列目) にプロパティ名を表示します.
Button1 では,全てのプロパティを取得します.Button2 と Button3 は,一部のプロパティだけを取得する際の参考コードとなっています.
Button2 では,ISWbemProperty オブジェクトにプロパティを取得し,そこから各々のプロパティ名とプロパティの値を取得しますが,Button3 では,OleVariant 型で処理します.どちらも結果は同じとなります.必要に応じて使い分けます.
このサンプルでは,ボタンクリックごとに WMI オブジェクトのインスタンスを生成,WMI サービスに接続していますが,実際にはアプリの起動時に実行すれば済みます.各々動作を独立させるために,このようにしているだけです.
必要と思われる部分だけをコピペして実行した結果,未定義のエラーの質問をされる方への,ささやかな対応策の 1 つと思ってください. |
[備考]
論理ディスクではなく,コンピュータに接続されている物理ドライブの情報は Win32_DiskDrive クラスで取得できます.
|
- 図3
- 設計時画面.TListView のカラム (列) は実行時に生成する
|
|
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, WbemScripting_TLB, ComCtrls, ExtCtrls, ComObj, ActiveX;
type
TForm1 = class(TForm)
Panel1: TPanel;
Panel2: TPanel;
Button1: TButton;
ListView1: TListView;
Button2: TButton;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private 宣言 }
function VarToString(const OleVar: OleVariant): String;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// 全論理ディスクの情報取得
// 全てのプロパティを取得
// TListViewの各行をプロパティとして表示
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
objWMILocator : ISWbemLocator;
objWMIService : ISWbemServices;
objPropSet : ISWbemObjectSet;
objPropSetEnum : IEnumVariant;
objTemp : OleVariant;
iValue : LongWord;
wmiPropSet : ISWbemPropertySet;
wmiPropSetEnum : IEnumVariant;
wmiProperty : ISWbemProperty;
AColumn : TListColumn;
AItem : TListItem;
RowNo : Integer;
begin
//WMIのオブジェクトを生成
objWMILocator := CoSWbemLocator.Create;
//WMIサービスに接続.引数は必要に応じて設定
objWMIService := objWMILocator.ConnectServer(
'',
'root\cimv2',
'',
'',
'',
'',
0,
nil);
//クエリーを実行して,プロパティのセットのオブジェクトを取得
objPropSet := objWMIService.ExecQuery(
'Select * From Win32_LogicalDisk',
'WQL',
wbemFlagReturnImmediately,
nil);
//プロパティのセットのコレクションを取得
objPropSetEnum := objPropSet._NewEnum as IEnumVariant;
//-------------------------------------------------------------------------
// 以下がプロパティの取得コード
//-------------------------------------------------------------------------
ListView1.Items.Clear;
ListView1.Items.BeginUpdate;
ListView1.Columns.Clear;
//プロパティ名のカラム作成(左端列)
AColumn := ListView1.Columns.Add;
AColumn.Caption := 'プロパティ';
AColumn.Width := 180;
//プロパティセットの数だけ繰返す
//このサンプルでは論理ディクスの数だけ
while objPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
//プロパティのセットを取得
wmiPropSet := (IUnknown(objTemp) as ISWBemObject).Properties_;
wmiPropSetEnum := (wmiPropSet._NewEnum) as IEnumVariant;
//プロパティセットごと(このサンプルでは論理ディスクごと)にカラムを追加
AColumn := ListView1.Columns.Add;
AColumn.Caption := IntToStr(ListView1.Columns.Count - 1);
AColumn.Width := 160;
RowNo := 0;
//プロパティの数だけ繰返す
//プロパティ名はName,プロパティの値はGet_Valueで取得
while wmiPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
if VarIsNull(objTemp) then Continue;
//プロパティを取得
wmiProperty := IUnknown(objTemp) as ISWBemProperty;
//最初のデータ取得の際には行を追加.TListViewのCaptionはプロパティ名
if ListView1.Columns.Count = 2 then begin
AItem := ListView1.Items.Add;
AItem.Caption := VarToString(wmiProperty.Name);
end;
//プロパティの値を表示
AItem := ListView1.Items.Item[RowNo];
AItem.SubItems.Add(VarToString(wmiProperty.Get_Value));
//次の行
RowNo := RowNo + 1;
end;
end;
ListView1.Items.EndUpdate;
end;
//=============================================================================
// 全論理ディスクの情報取得
// プロパティの一部だけを取得して表示する場合
// TListViewの各行をプロパティとして表示
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
objWMILocator : ISWbemLocator;
objWMIService : ISWbemServices;
objPropSet : ISWbemObjectSet;
objPropSetEnum : IEnumVariant;
objTemp : OleVariant;
iValue : LongWord;
wmiPropSet : ISWbemPropertySet;
wmiPropSetEnum : IEnumVariant;
wmiProperty : ISWbemProperty;
AColumn : TListColumn;
AItem : TListItem;
begin
//WMIのオブジェクトを生成
objWMILocator := CoSWbemLocator.Create;
//WMIサービスに接続.引数は必要に応じて設定
objWMIService := objWMILocator.ConnectServer(
'',
'root\cimv2',
'',
'',
'',
'',
0,
nil);
//クエリーを実行して,プロパティのセットのオブジェクトを取得
objPropSet := objWMIService.ExecQuery(
'Select * From Win32_LogicalDisk',
'WQL',
wbemFlagReturnImmediately,
nil);
//プロパティのセットのコレクションを取得
objPropSetEnum := objPropSet._NewEnum as IEnumVariant;
//-------------------------------------------------------------------------
// 以下がプロパティの取得コード
//-------------------------------------------------------------------------
ListView1.Items.Clear;
ListView1.Items.BeginUpdate;
ListView1.Columns.Clear;
//プロパティ名のカラム作成(左端列)
AColumn := ListView1.Columns.Add;
AColumn.Caption := 'プロパティ';
AColumn.Width := 180;
//プロパティセットの数だけ繰返す
//このサンプルでは論理ディクスの数だけ
while objPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
//プロパティのセットを取得
wmiPropSet := (IUnknown(objTemp) as ISWBemObject).Properties_;
wmiPropSetEnum := (wmiPropSet._NewEnum) as IEnumVariant;
//プロパティセットごと(このサンプルでは論理ディスクごと)にカラムを追加
AColumn := ListView1.Columns.Add;
AColumn.Caption := IntToStr(ListView1.Columns.Count - 1);
AColumn.Width := 160;
if ListView1.Items.Count = 0 then begin
ListView1.Items.Add.Caption := 'ドライブ名';
ListView1.Items.Add.Caption := '種類';
ListView1.Items.Add.Caption := 'サイズ';
ListView1.Items.Add.Caption := 'シリアル番号';
end;
//カラムに対応したプロパティを取出して表示
//CollectionItem.プロパティ名で取得する
AItem := ListView1.Items.Item[0];
wmiProperty := wmiPropSet.Item('Caption', 0);
AItem.SubItems.Add(VarToString(wmiProperty.Get_Value));
AItem := ListView1.Items.Item[1];
wmiProperty := wmiPropSet.Item('Description', 0);
AItem.SubItems.Add(VarToString(wmiProperty.Get_Value));
AItem := ListView1.Items.Item[2];
wmiProperty := wmiPropSet.Item('Size', 0);
AItem.SubItems.Add(VarToString(wmiProperty.Get_Value));
AItem := ListView1.Items.Item[3];
wmiProperty := wmiPropSet.Item('VolumeSerialNumber', 0);
AItem.SubItems.Add(VarToString(wmiProperty.Get_Value));
end;
ListView1.Items.EndUpdate;
end;
//=============================================================================
// 全論理ディスクの情報取得
// プロパティの一部だけを取得して表示する場合
// TListViewの各行をプロパティとして表示
//
// ISWbemPropertyとしてのプロパティを使用しないで,OleVariantから取得する例
//=============================================================================
procedure TForm1.Button3Click(Sender: TObject);
var
objWMILocator : ISWbemLocator;
objWMIService : ISWbemServices;
objPropSet : ISWbemObjectSet;
objPropSetEnum : IEnumVariant;
objTemp : OleVariant;
iValue : LongWord;
wmiPropSet : ISWbemPropertySet;
wmiPropSetEnum : IEnumVariant;
AColumn : TListColumn;
AItem : TListItem;
begin
//WMIのオブジェクトを生成
objWMILocator := CoSWbemLocator.Create;
//WMIサービスに接続.引数は必要に応じて設定
objWMIService := objWMILocator.ConnectServer(
'',
'root\cimv2',
'',
'',
'',
'',
0,
nil);
//クエリーを実行して,プロパティのセットのオブジェクトを取得
objPropSet := objWMIService.ExecQuery(
'Select * From Win32_LogicalDisk',
'WQL',
wbemFlagReturnImmediately,
nil);
//プロパティのセットのコレクションを取得
objPropSetEnum := objPropSet._NewEnum as IEnumVariant;
//-------------------------------------------------------------------------
// 以下がプロパティの取得コード
//-------------------------------------------------------------------------
ListView1.Items.Clear;
ListView1.Items.BeginUpdate;
ListView1.Columns.Clear;
//プロパティ名のカラム作成(左端列)
AColumn := ListView1.Columns.Add;
AColumn.Caption := 'プロパティ';
AColumn.Width := 180;
//プロパティセットの数だけ繰返す
//このサンプルでは論理ディクスの数だけ
while objPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
//プロパティのセットを取得
wmiPropSet := (IUnknown(objTemp) as ISWBemObject).Properties_;
wmiPropSetEnum := (wmiPropSet._NewEnum) as IEnumVariant;
//プロパティセットごと(このサンプルでは論理ディスクごと)にカラムを追加
AColumn := ListView1.Columns.Add;
AColumn.Caption := IntToStr(ListView1.Columns.Count - 1);
AColumn.Width := 160;
if ListView1.Items.Count = 0 then begin
ListView1.Items.Add.Caption := 'ドライブ名';
ListView1.Items.Add.Caption := '種類';
ListView1.Items.Add.Caption := 'サイズ';
ListView1.Items.Add.Caption := 'シリアル番号';
end;
//カラムに対応したプロパティを取出して表示
//CollectionItem.プロパティ名で取得する
AItem := ListView1.Items.Item[0];
AItem.SubItems.Add(VarToString(objTemp.Caption));
AItem := ListView1.Items.Item[1];
AItem.SubItems.Add(VarToString(objTemp.Description));
AItem := ListView1.Items.Item[2];
AItem.SubItems.Add(VarToString(objTemp.Size));
AItem := ListView1.Items.Item[3];
AItem.SubItems.Add(VarToString(objTemp.VolumeSerialNumber));
end;
ListView1.Items.EndUpdate;
end;
//=============================================================================
// OleVariantの値をString型に変換(再帰処理)
// 複数の値を持つプロパティがある.そこでこれを[]で括った結果を返すことにする
// そのためVarArrayも扱えるようにしたVarToStr関数
//=============================================================================
function TForm1.VarToString(const OleVar: OleVariant): String;
var
LowBound : Integer;
HighBound : Integer;
i : Integer;
begin
Result := '';
//配列の場合
if VarIsArray(OleVar) then begin
LowBound := VarArrayLowBound(OleVar, 1);
HighBound := VarArrayHighBound(OleVar, 1);
for i := LowBound to HighBound do begin
if i = HighBound then begin
Result := Result + VarToString(OleVar[i]);
end else begin
Result := Result + VarToString(OleVar[i]) + ',';
end;
end;
Result:='[' + Result + ']';
//単一の値を持つプロパティの場合
end else begin
Result := VarToStr(OleVar);
end;
if Result = '' then Result := 'NULL';
end;
end.
同じく Win32_LogicalDisk クラスをクエリーを実行しますが,クエリの where 句でドイブを指定して,特定のドライブだけのプロパティを取得します.
ここでは C: ドライブとしています. |
|
図6
設計時画面
|
|
図7
実行画面例 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, WbemScripting_TLB, ComCtrls, ExtCtrls, ComObj, ActiveX;
type
TForm1 = class(TForm)
Panel1: TPanel;
Panel2: TPanel;
Button1: TButton;
ListView1: TListView;
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
function VarToString(const OleVar: OleVariant): String;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// 指定ドライブのみの情報をクエリーで指定して取得
//
// このサンプルでは,設計時にカラムを作成している
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
objWMILocator : ISWbemLocator;
objWMIService : ISWbemServices;
objPropSet : ISWbemObjectSet;
objPropSetEnum : IEnumVariant;
objTemp : OleVariant;
iValue : LongWord;
wmiPropSet : ISWbemPropertySet;
wmiPropSetEnum : IEnumVariant;
wmiProperty : ISWbemProperty;
AItem : TListItem;
begin
//WMIのオブジェクトを生成
objWMILocator := CoSWbemLocator.Create;
//WMIサービスに接続.引数は必要に応じて設定
objWMIService := objWMILocator.ConnectServer(
'',
'root\cimv2',
'',
'',
'',
'',
0,
nil);
//クエリーを実行して,プロパティのセットのオブジェクトを取得
objPropSet := objWMIService.ExecQuery(
'Select * From Win32_LogicalDisk where name= "C:"',
'WQL',
wbemFlagReturnImmediately,
nil);
//プロパティのセットのコレクションを取得
objPropSetEnum := objPropSet._NewEnum as IEnumVariant;
//-------------------------------------------------------------------------
// 以下がプロパティの取得コード
//-------------------------------------------------------------------------
ListView1.Items.Clear;
ListView1.Items.BeginUpdate;
//プロパティセットの数だけ繰返す
//このサンプルでは論理ディクスの数だけ
while objPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
//プロパティのセットを取得
wmiPropSet := (IUnknown(objTemp) as ISWBemObject).Properties_;
wmiPropSetEnum := (wmiPropSet._NewEnum) as IEnumVariant;
//プロパティの数だけ繰返す
//プロパティ名はName,プロパティの値はGet_Valueで取得
while wmiPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
if VarIsNull(objTemp) then Continue;
//プロパティを取得
wmiProperty := IUnknown(objTemp) as ISWBemProperty;
//TListViewに行を追加.TListViewのCaptionはプロパティ名
AItem := ListView1. Items.Add;
AItem.Caption := VarToString(wmiProperty.Name);
AItem.SubItems.Add(VarToString(wmiProperty.Get_Value));
end;
end;
ListView1.Items.EndUpdate;
end;
//=============================================================================
// OleVariantの値をString型に変換(再帰処理)
// 複数の値を持つプロパティがある.そこでこれを[]で括った結果を返すことにする
// そのためVarArrayも扱えるようにしたVarToStr関数
//=============================================================================
function TForm1.VarToString(const OleVar: OleVariant): String;
var
LowBound : Integer;
HighBound : Integer;
i : Integer;
begin
Result := '';
//配列の場合
if VarIsArray(OleVar) then begin
LowBound := VarArrayLowBound(OleVar, 1);
HighBound := VarArrayHighBound(OleVar, 1);
for i := LowBound to HighBound do begin
if i = HighBound then begin
Result := Result + VarToString(OleVar[i]);
end else begin
Result := Result + VarToString(OleVar[i]) + ',';
end;
end;
Result:='[' + Result + ']';
//単一の値を持つプロパティの場合
end else begin
Result := VarToStr(OleVar);
end;
if Result = '' then Result := 'NULL';
end;
end.
クエリに Win32_PhysicalMemory クラスを指定して,メモリの情報を取得する例です.最初のサンプルと違うのはクエリで指定するクラス名の文字列だけです. |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, WbemScripting_TLB, ComCtrls, ExtCtrls, ComObj, ActiveX;
type
TForm1 = class(TForm)
Panel1: TPanel;
Panel2: TPanel;
Button1: TButton;
ListView1: TListView;
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
function VarToString(const OleVar: OleVariant): String;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// 物理メモリの情報取得
// 全てのプロパティを取得
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
objWMILocator : ISWbemLocator;
objWMIService : ISWbemServices;
objPropSet : ISWbemObjectSet;
objPropSetEnum : IEnumVariant;
objTemp : OleVariant;
iValue : LongWord;
wmiPropSet : ISWbemPropertySet;
wmiPropSetEnum : IEnumVariant;
wmiProperty : ISWbemProperty;
AColumn : TListColumn;
AItem : TListItem;
RowNo : Integer;
begin
//WMIのオブジェクトを生成
objWMILocator := CoSWbemLocator.Create;
//WMIサービスに接続.引数は必要に応じて設定
objWMIService := objWMILocator.ConnectServer(
'',
'root\cimv2',
'',
'',
'',
'',
0,
nil);
//クエリーを実行して,プロパティのセットのオブジェクトを取得
objPropSet := objWMIService.ExecQuery(
'Select * From Win32_PhysicalMemory',
'WQL',
wbemFlagReturnImmediately,
nil);
//プロパティのセットのコレクションを取得
objPropSetEnum := objPropSet._NewEnum as IEnumVariant;
//-------------------------------------------------------------------------
// 以下がプロパティの取得コード
//-------------------------------------------------------------------------
ListView1.Items.Clear;
ListView1.Items.BeginUpdate;
ListView1.Columns.Clear;
//プロパティ名のカラム作成(左端列)
AColumn := ListView1.Columns.Add;
AColumn.Caption := 'プロパティ';
AColumn.Width := 180;
//プロパティセットの数だけ繰返す
//このサンプルではメモリバンクの数だけ
while objPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
//プロパティのセットを取得
wmiPropSet := (IUnknown(objTemp) as ISWBemObject).Properties_;
wmiPropSetEnum := (wmiPropSet._NewEnum) as IEnumVariant;
//プロパティセットごとにカラムを追加
AColumn := ListView1.Columns.Add;
AColumn.Caption := IntToStr(ListView1.Columns.Count - 1);
AColumn.Width := 160;
RowNo := 0;
//プロパティの数だけ繰返す
//プロパティ名はName,プロパティの値はGet_Valueで取得
while wmiPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
if VarIsNull(objTemp) then Continue;
//プロパティを取得
wmiProperty := IUnknown(objTemp) as ISWBemProperty;
//最初のデータ取得の際には行を追加.TListViewのCaptionはプロパティ名
if ListView1.Columns.Count = 2 then begin
AItem := ListView1.Items.Add;
AItem.Caption := VarToString(wmiProperty.Name);
end;
//プロパティの値を表示
AItem := ListView1.Items.Item[RowNo];
AItem.SubItems.Add(VarToString(wmiProperty.Get_Value));
//次の行
RowNo := RowNo + 1;
end;
end;
ListView1.Items.EndUpdate;
end;
//=============================================================================
// OleVariantの値をString型に変換(再帰処理)
// 複数の値を持つプロパティがある.そこでこれを[]で括った結果を返すことにする
// そのためVarArrayも扱えるようにしたVarToStr関数
//=============================================================================
function TForm1.VarToString(const OleVar: OleVariant): String;
var
LowBound : Integer;
HighBound : Integer;
i : Integer;
begin
Result := '';
//配列の場合
if VarIsArray(OleVar) then begin
LowBound := VarArrayLowBound(OleVar, 1);
HighBound := VarArrayHighBound(OleVar, 1);
for i := LowBound to HighBound do begin
if i = HighBound then begin
Result := Result + VarToString(OleVar[i]);
end else begin
Result := Result + VarToString(OleVar[i]) + ',';
end;
end;
Result:='[' + Result + ']';
//単一の値を持つプロパティの場合
end else begin
Result := VarToStr(OleVar);
end;
if Result = '' then Result := 'NULL';
end;
end.
クエリに Win32_Processor クラスを指定して,メモリの情報を取得する例です.最初のサンプルと違うのはクエリで指定するクラス名の文字列だけです. |
|
図9
実行画面例
|
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, WbemScripting_TLB, ComCtrls, ExtCtrls, ComObj, ActiveX;
type
TForm1 = class(TForm)
Panel1: TPanel;
Panel2: TPanel;
Button1: TButton;
ListView1: TListView;
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
function VarToString(const OleVar: OleVariant): String;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// プロセッサ(CPU)の情報取得
// 全てのプロパティを取得
//
// 取得まで少し時間がかかる.LoadPercentage(CPU使用率)を除くと速くなる
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
objWMILocator : ISWbemLocator;
objWMIService : ISWbemServices;
objPropSet : ISWbemObjectSet;
objPropSetEnum : IEnumVariant;
objTemp : OleVariant;
iValue : LongWord;
wmiPropSet : ISWbemPropertySet;
wmiPropSetEnum : IEnumVariant;
wmiProperty : ISWbemProperty;
AColumn : TListColumn;
AItem : TListItem;
RowNo : Integer;
begin
//WMIのオブジェクトを生成
objWMILocator := CoSWbemLocator.Create;
//WMIサービスに接続.引数は必要に応じて設定
objWMIService := objWMILocator.ConnectServer(
'',
'root\cimv2',
'',
'',
'',
'',
0,
nil);
//クエリーを実行して,プロパティのセットのオブジェクトを取得
objPropSet := objWMIService.ExecQuery(
'Select * From Win32_Processor',
'WQL',
wbemFlagReturnImmediately,
nil);
//プロパティのセットのコレクションを取得
objPropSetEnum := objPropSet._NewEnum as IEnumVariant;
//-------------------------------------------------------------------------
// 以下がプロパティの取得コード
//-------------------------------------------------------------------------
ListView1.Items.Clear;
ListView1.Items.BeginUpdate;
ListView1.Columns.Clear;
//プロパティ名のカラム作成(左端列)
AColumn := ListView1.Columns.Add;
AColumn.Caption := 'プロパティ';
AColumn.Width := 180;
//プロパティセットの数だけ繰返す
//このサンプルではCPUの数だけ
while objPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
//プロパティのセットを取得
wmiPropSet := (IUnknown(objTemp) as ISWBemObject).Properties_;
wmiPropSetEnum := (wmiPropSet._NewEnum) as IEnumVariant;
//プロパティセットごとにカラムを追加
AColumn := ListView1.Columns.Add;
AColumn.Caption := IntToStr(ListView1.Columns.Count - 1);
AColumn.Width := 200;
RowNo := 0;
//プロパティの数だけ繰返す
//プロパティ名はName,プロパティの値はGet_Valueで取得
while wmiPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
if VarIsNull(objTemp) then Continue;
//プロパティを取得
wmiProperty := IUnknown(objTemp) as ISWBemProperty;
//最初のデータ取得の際には行を追加.TListViewのCaptionはプロパティ名
if ListView1.Columns.Count = 2 then begin
AItem := ListView1.Items.Add;
AItem.Caption := VarToString(wmiProperty.Name);
end;
//プロパティの値を表示
AItem := ListView1.Items.Item[RowNo];
AItem.SubItems.Add(VarToString(wmiProperty.Get_Value));
//次の行
RowNo := RowNo + 1;
end;
end;
ListView1.Items.EndUpdate;
end;
//=============================================================================
// OleVariantの値をString型に変換(再帰処理)
// 複数の値を持つプロパティがある.そこでこれを[]で括った結果を返すことにする
// そのためVarArrayも扱えるようにしたVarToStr関数
//=============================================================================
function TForm1.VarToString(const OleVar: OleVariant): String;
var
LowBound : Integer;
HighBound : Integer;
i : Integer;
begin
Result := '';
//配列の場合
if VarIsArray(OleVar) then begin
LowBound := VarArrayLowBound(OleVar, 1);
HighBound := VarArrayHighBound(OleVar, 1);
for i := LowBound to HighBound do begin
if i = HighBound then begin
Result := Result + VarToString(OleVar[i]);
end else begin
Result := Result + VarToString(OleVar[i]) + ',';
end;
end;
Result:='[' + Result + ']';
//単一の値を持つプロパティの場合
end else begin
Result := VarToStr(OleVar);
end;
if Result = '' then Result := 'NULL';
end;
end.
CPU の論理的な数は,System の CPUCount 関数でも取得できます. |
|
図10
プロセッサの論理的な数 |
procedure TForm1.Button1Click(Sender: TObject);
var
CntCpu : Integer;
begin
CntCpu := System.CPUCount;
MessageBox(Handle, PChar(IntToStr(CntCpu)), '情報', MB_ICONINFORMATION);
end;
Delphi のコミュニティの場で,CPU の温度を調べる内容の書き込みがありました.
WMI 名前空間の MSAcpi_ThermalZoneTemperature クラスを使用すると取得できるようです.CPU には温度計測用のプローブが付いています.おそらくその値を取得するものと思われます.
下のコードはそのサンプルです.本ページの最初のサンプルに以下の変更をしています.
- (1) ConnectServer メソッドの root\cimv2 を root\WMI に変更
- (2) ExecQuery メソッドの From 句のクラス名を MSAcpi_ThermalZoneTemperature に変更
- (3) 管理者権限でないと実行しないようにするコードを追加
上記以外の変更はしていません.
MSAcpi_ThermalZoneTemperature は,管理者権限で実行しないとクエリの結果として何も取得できません.そのため,管理者権限での実行の判定をしています.
結果のプロパティセットの数が 2 つあるのは デュアルコアの CPU だからです.
MSAcpi_ThermalZoneTemperature クラスのプロパティは,環境によっては,温度等のプロパティが取得できない場合があるようです. |
|
図11
実行結果の例 |
リスト6
プロセッサ (CPU) の温度情報を取得
本ページの最初のサンプルコードの,名前空間とクラス名を変更しただけ |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, WbemScripting_TLB, ComCtrls, ExtCtrls, ComObj, ActiveX;
type
TForm1 = class(TForm)
Panel1: TPanel;
Panel2: TPanel;
Button1: TButton;
ListView1: TListView;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private 宣言 }
function VarToString(const OleVar: OleVariant): String;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
ShlObj;
{$R *.dfm}
//=============================================================================
// フォーム生成時の処理
// クエリの対象となるクラスを設定
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Edit1.Text := 'MSAcpi_ThermalZoneTemperature';
end;
//=============================================================================
// CPUの温度関係の情報を取得
// WMI名前空間のMSAcpi_ThermalZoneTemperatureクラスを使用
//
// 管理者権限で実行しないと取得に失敗する
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
objWMILocator : ISWbemLocator;
objWMIService : ISWbemServices;
objPropSet : ISWbemObjectSet;
objPropSetEnum : IEnumVariant;
objTemp : OleVariant;
iValue : LongWord;
wmiPropSet : ISWbemPropertySet;
wmiPropSetEnum : IEnumVariant;
wmiProperty : ISWbemProperty;
AColumn : TListColumn;
AItem : TListItem;
RowNo : Integer;
strClassName : String;
begin
//IsUserAnAdminの使用にはusesにShlObjが必要
if not IsUserAnAdmin then begin
MessageBox(Handle, '管理者権限で実行してください', '情報', MB_ICONINFORMATION);
exit;
end;
strClassName := Trim(Edit1.Text);
//WMIのオブジェクトを生成
objWMILocator := CoSWbemLocator.Create;
//WMIサービスに接続.引数は必要に応じて設定
objWMIService := objWMILocator.ConnectServer(
'',
'root\WMI',
'',
'',
'',
'',
0,
nil);
//クエリーを実行して,プロパティのセットのオブジェクトを取得
objPropSet := objWMIService.ExecQuery(
'Select * From ' + strClassName,
'WQL',
wbemFlagReturnImmediately,
nil);
//プロパティのセットのコレクションを取得
objPropSetEnum := objPropSet._NewEnum as IEnumVariant;
//-------------------------------------------------------------------------
// 以下がプロパティの取得コード
//-------------------------------------------------------------------------
ListView1.Items.Clear;
ListView1.Items.BeginUpdate;
ListView1.Columns.Clear;
//プロパティ名のカラム作成(左端列)
AColumn := ListView1.Columns.Add;
AColumn.Caption := 'プロパティ';
AColumn.Width := 200;
//プロパティセットの数だけ繰返す
while objPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
//プロパティのセットを取得
wmiPropSet := (IUnknown(objTemp) as ISWBemObject).Properties_;
wmiPropSetEnum := (wmiPropSet._NewEnum) as IEnumVariant;
//プロパティセットごとにカラムを追加
AColumn := ListView1.Columns.Add;
AColumn.Caption := IntToStr(ListView1.Columns.Count - 1);
AColumn.Width := 190;
RowNo := 0;
//プロパティの数だけ繰返す
//プロパティ名はName,プロパティの値はGet_Valueで取得
while wmiPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
if VarIsNull(objTemp) then Continue;
//プロパティを取得
wmiProperty := IUnknown(objTemp) as ISWBemProperty;
//最初のデータ取得の際には行を追加.TListViewのCaptionはプロパティ名
if ListView1.Columns.Count = 2 then begin
AItem := ListView1.Items.Add;
AItem.Caption := VarToString(wmiProperty.Name);
end;
//プロパティの値を表示
AItem := ListView1.Items.Item[RowNo];
AItem.SubItems.Add(VarToString(wmiProperty.Get_Value));
//次の行
RowNo := RowNo + 1;
end;
end;
ListView1.Items.EndUpdate;
end;
//=============================================================================
// OleVariantの値をString型に変換(再帰処理)
// 複数の値を持つプロパティがある.そこでこれを[]で括った結果を返すことにする
// そのためVarArrayも扱えるようにしたVarToStr関数
//=============================================================================
function TForm1.VarToString(const OleVar: OleVariant): String;
var
LowBound : Integer;
HighBound : Integer;
i : Integer;
begin
Result := '';
//配列の場合
if VarIsArray(OleVar) then begin
LowBound := VarArrayLowBound(OleVar, 1);
HighBound := VarArrayHighBound(OleVar, 1);
for i := LowBound to HighBound do begin
if i = HighBound then begin
Result := Result + VarToString(OleVar[i]);
end else begin
Result := Result + VarToString(OleVar[i]) + ',';
end;
end;
Result:='[' + Result + ']';
//単一の値を持つプロパティの場合
end else begin
Result := VarToStr(OleVar);
end;
if Result = '' then Result := 'NULL';
end;
end.
上のコードは,MSAcpi_ThermalZoneTemperature クラスのプロパティ全てを取得しています.
温度関係のプロパティである InstanceName と CurrentTemperature の値だけを取得するようにしたのが次のコードです.
CurrentTemperature プロパティの単位はケルビン (絶対温度) の 10 倍の値となっています.そこで,下のコードでは,ConvUtils.Convert で摂氏 (セルシウス) 温度の値に換算しています. |
|
図12
実行結果の例
|
リスト7
プロセッサ (CPU) の温度を取得して TMemo に表示 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, WbemScripting_TLB, ComCtrls, ExtCtrls, ComObj, ActiveX;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
ConvUtils, StdConvs, ShlObj;
{$R *.dfm}
//=============================================================================
// CPUの温度の情報を取得
// WMI名前空間のMSAcpi_ThermalZoneTemperatureクラスを使用
// 温度の値だけを取得する例
//
// 管理者権限で実行しないと取得に失敗する
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
objWMILocator : ISWbemLocator;
objWMIService : ISWbemServices;
objPropSet : ISWbemObjectSet;
objPropSetEnum : IEnumVariant;
objTemp : OleVariant;
iValue : LongWord;
wmiPropSet : ISWbemPropertySet;
wmiProperty : ISWbemProperty;
strClassName : String;
TempInKelvin : Double;
TempInCelsius : Double;
begin
//IsUserAnAdminの使用にはusesにShlObjが必要
if not IsUserAnAdmin then begin
MessageBox(Handle, '管理者権限で実行してください', '情報', MB_ICONINFORMATION);
exit;
end;
Memo1.Lines.Clear;
strClassName := 'MSAcpi_ThermalZoneTemperature';
//WMIのオブジェクトを生成
objWMILocator := CoSWbemLocator.Create;
//WMIサービスに接続.引数は必要に応じて設定
objWMIService := objWMILocator.ConnectServer(
'',
'root\WMI',
'',
'',
'',
'',
0,
nil);
//クエリーを実行して,プロパティのセットのオブジェクトを取得
objPropSet := objWMIService.ExecQuery(
'Select * From ' + strClassName,
'WQL',
wbemFlagReturnImmediately,
nil);
//プロパティのセットのコレクションを取得
objPropSetEnum := objPropSet._NewEnum as IEnumVariant;
//-------------------------------------------------------------------------
// 以下がプロパティの取得コード
//-------------------------------------------------------------------------
//プロパティセットの数だけ繰返す
while objPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
//プロパティのセットを取得
wmiPropSet := (IUnknown(objTemp) as ISWBemObject).Properties_;
//InstanceNameプロパティを取得
wmiProperty := wmiPropSet.Item('InstanceName', 0);
if not VarIsNull(wmiProperty.Get_Value) then begin
Memo1.Lines.Add(VarToStr(wmiProperty.Get_Value));
end;
//CurrentTemperatureプロパティを取得
wmiProperty := wmiPropSet.Item('CurrentTemperature', 0);
if not VarIsNull(wmiProperty.Get_Value) then begin
//CurrentTemperatureはケルビン温度(絶対温度)を10倍した値なので
//10で割って摂氏の値に換算
//この式のコードの実行にはusesにConvUtils, StdConvsが必要
TempInKelvin := wmiProperty.Get_Value / 10.0;
TempInCelsius := ConvUtils.Convert(TempInKelvin, tuKelvin, tuCelsius);
Memo1.Lines.Add(FormatFloat('#####0.0', TempInCelsius));
end;
Memo1.Lines.Add('-------------------------');
end;
end;
end.
|