Delphi Programming / Object Pascal
[掲載 2008年05月02日] [更新 2013年09月04日] Delphi サンプルプログラム集 |
901_WMI ソフトウェア関係情報の取得 |
動作確認等 |
Windows 7 U64(SP1) + Delphi XE Pro |
|
901_WMI_SoftWare.zip [1,800 KB] 2013年09月04日版 (EXE 同梱) |
- 2010年07月29日
- プロパティ取得のループ処理を while 文を使用するコードに統一
|
- 2013年09月03日
- [898_WMI イントロダクション] の更新に伴い,コードを整備し,記事も修正
|
WMI でハードウェア,ソフトウェアの情報,プロパティということになりますが,これらを取得する手順は次のようになります.
- (1) WMI オブジェクトのインスタンスを生成
- (2) そのインスタンスを WMI サービスに接続
- (3) そのサービスに対して,プロパティのセットを取得するクエリーを実行
- (4) クエリの結果からプロパティを取得していく
1 番目と 2 番目のコードはいつもほとんど同じです.
3 番目のクエリ文で,使用する Win32_LogicalDisk と言ったクラス名と呼ばれる部分を,目的に応じて変えることになります.どのようなクラスに,どのような機能があるかは,[WMI イントロダクション] のページの参考リンクの記事を参考にしてください.
本ページでは,Win32 Classes クラスの Installed Applications Classes の一部のクラスを使用して,ソフトウェアの情報を取得します. |
クエリに Win32_SoftwareFeature クラスを指定して,インストールされている全ソフトウェアをリストします.
[900_WMI を使用したハードウェア関係情報の取得] では,プロパティの数だけ行を作成しましたが,本ページでは,各カラムをプロパティとしています.したがって,TListView の行数がインストールされてるいるソフトウェアの数ということになります.
このサンプルのクエリの実行は,非常に時間がかかります. |
- 図1
- 設計時画面.本ページのサンプルでは全て同じ
- カラムは実行時に作成する
|
|
- 図2
- 実行例.8484 はインストールされているソフトの数
- このようなことほとんど必要性はないと思うが,クエリの実行に非常に時間がかかる
|
|
リスト1
インストールされている全ソフトウェアのリストを取得 |
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;
Panel3: TPanel;
Panel4: TPanel;
ListView1: TListView;
Button1: TButton;
ProgressBar1: TProgressBar;
Label1: TLabel;
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;
CreateRowFlag : Boolean;
begin
Screen.Cursor := crHourGlass;
//WMIのオブジェクトを生成
objWMILocator := CoSWbemLocator.Create;
//WMIサービスに接続.引数は必要に応じて設定
objWMIService := objWMILocator.ConnectServer(
'',
'root\cimv2',
'',
'',
'',
'',
0,
nil);
//クエリーを実行して,プロパティのセットのオブジェクトを取得
objPropSet := objWMIService.ExecQuery(
'Select * From Win32_SoftwareFeature',
'WQL',
wbemFlagReturnImmediately,
nil);
//プロパティのセットのコレクションを取得
objPropSetEnum := objPropSet._NewEnum as IEnumVariant;
//-------------------------------------------------------------------------
// 以下がプロパティの取得コード
//-------------------------------------------------------------------------
ListView1.Items.Clear;
ListView1.Items.BeginUpdate;
ListView1.Columns.Clear;
Label1.Caption := '';
ProgressBar1.Position := 0;
ProgressBar1.Min := 0;
ProgressBar1.Max := objPropSet.Count;
//取得したソフトの数を表示
Label1.Caption := IntToStr(objPropSet.Count);
//プロパティセットの数だけ繰返す
//このサンプルでは論理ディクスの数だけ
while objPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
//プロパティのセットを取得
wmiPropSet := (IUnknown(objTemp) as ISWBemObject).Properties_;
wmiPropSetEnum := (wmiPropSet._NewEnum) as IEnumVariant;
CreateRowFlag := True;
//プロパティの数だけ繰返す
//プロパティ名はName,プロパティの値はGet_Valueで取得
while wmiPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
if VarIsNull(objTemp) then Continue;
//プロパティを取得
wmiProperty := IUnknown(objTemp) as ISWBemProperty;
//プロパティセットの最初のプロパティ取得の際に行を追加
//後のプロパティはSubItems(列)方向に追加していく
if CreateRowFlag then begin
AItem := ListView1.Items.Add;
AItem.Caption := VarToString(wmiProperty.Get_Value);
CreateRowFlag := False;
end else begin
AItem.SubItems.Add(VarToString(wmiProperty.Get_Value));
end;
//次のプロパティ表示用にカラム(列)を追加
if ListView1.Items.Count = 1 then begin
AColumn := ListView1.Columns.Add;
AColumn.Caption := VarToString(wmiProperty.Name);
AColumn.Width := 130;
end;
Application.ProcessMessages;
Sleep(1);
end;
ProgressBar1.Position := ProgressBar1.Position + 1;
end;
ListView1.Items.EndUpdate;
Screen.Cursor := crDefault;
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.
下図は,Caption プロパティに Microsoft という文字列が含まれるソフトだけを取得した結果です.その下のコードのように,クエリ文の where 句で指定しています. |
- 図3
- Caption プロパティに Microsoft の文字が含まれるいるソフトだけのリスト
|
|
objPropSet := objWMIService.ExecQuery(
'Select * From Win32_SoftwareFeature '
+ 'where caption like "%Microsoft%"',
'WQL',
wbemFlagReturnImmediately,
nil);
クエリに Win32_Product クラスを使用して,Windows のインストーラである MSI でインストールしたアプリケーションの一覧を取得して表示します.
上のサンプルと違うのはクエリで指定するクラス名の文字列だけです. |
- 図4
- 実行例.140 はインストールされている MSI アプリケーションの数
|
|
リスト2
MSI でインストールしたアプリのリストを取得
上のサンプルと違うのは,クエリ文のクラス名の部分だけ |
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;
Panel3: TPanel;
Panel4: TPanel;
ListView1: TListView;
Button1: TButton;
ProgressBar1: TProgressBar;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
function VarToString(const OleVar: OleVariant): String;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// MSIでインストールした製品のリストを取得して表示
// クエリーの実行に少し時間がかかるので注意
//=============================================================================
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;
CreateRowFlag : Boolean;
begin
Screen.Cursor := crHourGlass;
//WMIのオブジェクトを生成
objWMILocator := CoSWbemLocator.Create;
//WMIサービスに接続.引数は必要に応じて設定
objWMIService := objWMILocator.ConnectServer(
'',
'root\cimv2',
'',
'',
'',
'',
0,
nil);
//クエリーを実行して,プロパティのセットのオブジェクトを取得
objPropSet := objWMIService.ExecQuery(
'Select * From Win32_Product',
'WQL',
wbemFlagReturnImmediately,
nil);
//プロパティのセットのコレクションを取得
objPropSetEnum := objPropSet._NewEnum as IEnumVariant;
//-------------------------------------------------------------------------
// 以下がプロパティの取得コード
//-------------------------------------------------------------------------
ListView1.Items.Clear;
ListView1.Items.BeginUpdate;
ListView1.Columns.Clear;
Label1.Caption := '';
ProgressBar1.Position := 0;
ProgressBar1.Min := 0;
ProgressBar1.Max := objPropSet.Count;
//取得したソフトの数を表示
Label1.Caption := IntToStr(objPropSet.Count);
//プロパティセットの数だけ繰返す
//このサンプルでは論理ディクスの数だけ
while objPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
//プロパティのセットを取得
wmiPropSet := (IUnknown(objTemp) as ISWBemObject).Properties_;
wmiPropSetEnum := (wmiPropSet._NewEnum) as IEnumVariant;
CreateRowFlag := True;
//プロパティの数だけ繰返す
//プロパティ名はName,プロパティの値はGet_Valueで取得
while wmiPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
if VarIsNull(objTemp) then Continue;
//プロパティを取得
wmiProperty := IUnknown(objTemp) as ISWBemProperty;
//プロパティセットの最初のプロパティ取得の際に行を追加
//後のプロパティはSubItems(列)方向に追加していく
if CreateRowFlag then begin
AItem := ListView1.Items.Add;
AItem.Caption := VarToString(wmiProperty.Get_Value);
CreateRowFlag := False;
end else begin
AItem.SubItems.Add(VarToString(wmiProperty.Get_Value));
end;
//次のプロパティ表示用にカラム(列)を追加
if ListView1.Items.Count = 1 then begin
AColumn := ListView1.Columns.Add;
AColumn.Caption := VarToString(wmiProperty.Name);
AColumn.Width := 130;
end;
Application.ProcessMessages;
Sleep(1);
end;
ProgressBar1.Position := ProgressBar1.Position + 1;
end;
ListView1.Items.EndUpdate;
Screen.Cursor := crDefault;
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_Process クラスを使用して,プロセスのリストを取得して表示します.
上のサンプルと違うのはクエリーで指定するクラス名の文字列だけです. |
リスト3
プロセスのリストを取得
上のサンプルと違うのは,クエリ文のクラス名の部分だけ |
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;
Panel3: TPanel;
Panel4: TPanel;
ListView1: TListView;
Button1: TButton;
ProgressBar1: TProgressBar;
Label1: TLabel;
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;
CreateRowFlag : Boolean;
begin
Screen.Cursor := crHourGlass;
//WMIのオブジェクトを生成
objWMILocator := CoSWbemLocator.Create;
//WMIサービスに接続.引数は必要に応じて設定
objWMIService := objWMILocator.ConnectServer(
'',
'root\cimv2',
'',
'',
'',
'',
0,
nil);
//クエリーを実行して,プロパティのセットのオブジェクトを取得
objPropSet := objWMIService.ExecQuery(
'Select * From Win32_Process',
'WQL',
wbemFlagReturnImmediately,
nil);
//プロパティのセットのコレクションを取得
objPropSetEnum := objPropSet._NewEnum as IEnumVariant;
//-------------------------------------------------------------------------
// 以下がプロパティの取得コード
//-------------------------------------------------------------------------
ListView1.Items.Clear;
ListView1.Items.BeginUpdate;
ListView1.Columns.Clear;
Label1.Caption := '';
ProgressBar1.Position := 0;
ProgressBar1.Min := 0;
ProgressBar1.Max := objPropSet.Count;
//取得したソフトの数を表示
Label1.Caption := IntToStr(objPropSet.Count);
//プロパティセットの数だけ繰返す
//このサンプルでは論理ディクスの数だけ
while objPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
//プロパティのセットを取得
wmiPropSet := (IUnknown(objTemp) as ISWBemObject).Properties_;
wmiPropSetEnum := (wmiPropSet._NewEnum) as IEnumVariant;
CreateRowFlag := True;
//プロパティの数だけ繰返す
//プロパティ名はName,プロパティの値はGet_Valueで取得
while wmiPropSetEnum.Next(1, objTemp, iValue) = 0 do begin
if VarIsNull(objTemp) then Continue;
//プロパティを取得
wmiProperty := IUnknown(objTemp) as ISWBemProperty;
//プロパティセットの最初のプロパティ取得の際に行を追加
//後のプロパティはSubItems(列)方向に追加していく
if CreateRowFlag then begin
AItem := ListView1.Items.Add;
AItem.Caption := VarToString(wmiProperty.Get_Value);
CreateRowFlag := False;
end else begin
AItem.SubItems.Add(VarToString(wmiProperty.Get_Value));
end;
//次のプロパティ表示用にカラム(列)を追加
if ListView1.Items.Count = 1 then begin
AColumn := ListView1.Columns.Add;
AColumn.Caption := VarToString(wmiProperty.Name);
AColumn.Width := 130;
end;
Application.ProcessMessages;
Sleep(1);
end;
ProgressBar1.Position := ProgressBar1.Position + 1;
end;
ListView1.Items.EndUpdate;
Screen.Cursor := crDefault;
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.
04_OS ( Windows のバージョン等 ) の情報 |
Windows のバージョン情報等は,Win32_OperatingSystem を使用すると取得できます.
以下のリンクの記事に実際の操作結果の図があります. |
|