Vistaで適応済更新プログラムを一覧取得するには?

解決


GT-BASS  2009-02-10 18:17:33  No: 33315

いつも皆さんの知識と知恵を拝見させて頂き感謝しております。

さて、私が行いたいのは、Windows Vistaマシンの既にインストールされているWindows更新プログラムをDelphi5 Ent.でリストとして取得する事、つまりはVistaのコントロールパネルから辿っていくと表示される「インストールされている更新プログラム」をリストとして取得する事です。

Windows 2K,XPではレジストリのインストールされているソフトウエア一覧にWindowsの更新プログラムも含まれており取得できていました。
しかし、Vistaでは更新プログラムの一覧はどうやら別の場所に格納されている様です。

色々探した結果、MSDN Visual C++フォーラムで私が意図する事とまったく同じ内容の質問を見つけたのですが、「MsiEnumPaches...」以降の意味が分からずお手上げ状態です。

どうぞよろしくお願いいたします。


ofZ  2009-02-10 20:12:24  No: 33316

現在Vista環境がないので、Vistaテストしていないのですが・・・
XPでは、動いているように見えます。

環境 Windows XP SP3 + Delphi5

まず、以下を参考にタイプライブラリを取り込む
Delphi de WMI
http://homepage3.nifty.com/KENCH/open/wmi/delphi_wmi.htm

usesに以下3つ追加
WbemScripting_TLB, ComObj, ActiveX

TButton, TListBoxを配置して
ボタンクリックイベントを以下のようにする

procedure TForm1.Button1Click(Sender: TObject);
var
  locator: ISWbemLocator;
  services: ISWbemServices;
  qfeSet: ISWbemObjectSet;
  tmpEnum: IEnumVariant;
  qfe: OleVariant;
  idx: Integer;
  value: Cardinal;
begin
  locator := CreateOleObject('WbemScripting.SWbemLocator') as ISWbemLocator;
  services := locator.ConnectServer('.', '', '', '', '', '', 0, nil);
  qfeSet := services.ExecQuery('Select * From Win32_QuickFixEngineering',
     'WQL', wbemFlagReturnImmediately, nil);
  ListBox1.Items.Clear;
  tmpEnum := qfeSet._NewEnum as IEnumVariant;
  for idx := 1 to qfeSet.Count-1 do begin
    tmpEnum.Next(1, qfe, value);
    ListBox1.Items.Add(qfe.HotFixID + ' | ' +
      qfe.Description + ' | ' +
      qfe.ServicePackInEffect + ' | ' +
      qfe.InstalledOn + ' | ' +
      qfe.InstalledBy);
  end;
end;

補足
サンプル見てちょっと作ったので、各行の意味はさっぱりわかりません。

参考URL
Delphi de WMI
http://homepage3.nifty.com/KENCH/open/wmi/delphi_wmi.htm

Windowsユーザーのためのワンポイント・レッスン  第58回
のサンプルプログラム
http://itpro.nikkeibp.co.jp/prembk/ITPro/ITBASIC/20050225/156702/


GT-BASS  2009-02-10 21:03:04  No: 33317

ofZさん
早速のレスを有難うございます。
参考URLもよく読んでから試してみたいと考えています。
とりあえずは御礼まで。


GT-BASS  2009-02-10 23:42:04  No: 33318

試してみました。
Vistaでも取得できました。有難うございます。

ただ、通常の開発環境であるWin 2K+Delphi5 Ent.で走らせて見たところ、大量にリストアップされて面食らってしまいました。

私の認識だった「Windows 2K,XPでは、レジストリに記載されたインストール・ソフトウエア一覧にWindows更新プログラムが全て含まれている」が間違っていました。
WMIについて調べてみてから、以下の3つの情報を比べてみました。
  (1) レジストリから入手したインストールされているソフト一覧
  (2) ofZさんのサンプルコード
  (3) IEで調べたWindows Update記録
今現在は、Windows Updateの更新プログラムは「レジストリから入手したインストールされているソフト一覧」で入手するのではなく、WMIで入手するのが正しいと結論しています。
そもそも、「インストールプログラムにWindows更新プログラムが表示されている」との状況証拠から、「Windows更新プログラムの全てがインストールプログラムに表示される」と結論付けられるはずも無く、数を数えてもいなかった私がいいかげんでした。

今回の私の目的では、ofZさんのサンプル中 qfe.HotFixIDとqfe.Descriptionが必要となります。
本当に有難う御座いました。


春来りなば…  2009-02-11 02:14:11  No: 33319

真琴:「ハルコさん、イチイチWin32_QuickFixEngineeringクラスのプロパティ名を指定してその値を取得するのは面倒よね? 全部まとめて取得できないの?」
春子:「だったら、プロパティ名も列挙すればイイんじゃない?」
真琴:「え? プロパティ名も列挙? どうやるの?」
春子:「こうかな?」

procedure TForm1.Button1Click(Sender: TObject);
 function VarToString(const OV: OleVariant): string;
 var
  LB, HB, i: Integer;
 begin
  if VarIsArray(OV) then begin
   Result := '[';
   LB := VarArrayLowBound(OV, 1);
   HB := VarArrayHighBound(OV, 1);
   for i := LB to HB do begin
    result := Result + VarToString(OV[i]);
    if i <> HB then Result := Result + ',';
   end;
   Result := Result + ']';
  end else begin
   Result := VarToStr(OV);
  end;
 end;
var
  Locator: ISWbemLocator;
  Services: ISWbemServices;
  ISWOSet: ISWbemObjectSet;
  Enum1, Enum2: IEnumVariant;
  ORow, OCol: OleVariant;
  i, j: Integer;
  Value: Integer;
begin
  Locator  := CoSWbemLocator.Create as ISWbemLocator;
  Services := Locator.ConnectServer('.', '', '', '', '', '', 0, nil);
  ISWOSet := Services.ExecQuery('Select * From Win32_QuickFixEngineering', 'WQL', WbemFlagReturnImmediately, nil);
  Enum1 := ISWOSet._NewEnum as IEnumVariant;
  ListBox1.Clear;
  for i := 1 to ISWOSet.Count do begin
   Enum1.Next(1, ORow, @Value);
   if Value <= 0 then Break;
   if VarIsNull(ORow) then Continue;
   Enum2 := IUnknown(ORow.Properties_._NewEnum) as IEnumVariant;
   for j := 1 to ORow.Properties_.Count do begin
    Enum2.Next(1, OCol, @Value);
    if Value <= 0 then Break;
    if VarIsNull(OCol) then Continue;
    ListBox1.Items.Add(Format('%s=%s', [VarToStr(OCol.Name), VarToString(OCol.Value)]));
   end;
   ListBox1.Items.Add('');
  end;
end;

真琴:「あれ? このコードでは、Enum.Next()の3番目の引数がポインタになってるけど?」
春子:「Delphiのバージョンが古いと、ポインタでなくちゃダメなのよ」
春子:「あ、そうなの…、それにしても XPなんかで、全部一度に列挙するとスゴイ数よね^^;」
春子:「それだけセキュリティホールが多かったってコト」
真琴:「だけど、こんなに多いと、特定のパッチがあたってるかを調べるのも面倒…」
春子:「それなら、特定のパッチとか、特定のサービスパックだけとかも指定できるよ、マコト」
真琴:「ホント? じゃぁ、それも教えて?」
春子:「たとえば、特定のパッチKB938127だけとか、SP2だけとかなら、QUERY文字列は…」

 Select * From Win32_QuickFixEngineering where HotFixID="KB938127"
 Select * From Win32_QuickFixEngineering where ServicePackInEffect="SP2"

真琴:「ふ〜ん、これって、データベースのQUERYそっくりじゃない?」
春子:「そう、データベースに慣れてる人はラクかな?」
真琴:「ハルコさん、昨日はスゴク寒かったのに、今日はポカポカ暖かくて、ナンか春になったみたい」
春子:「うん、そうだネ、もう春はすぐそこ」
真琴:「"春来りなば夏遠からじ"よね? ハルコさん」
春子:「え?それ違うでしょ? マコト、"冬来りなば春遠からじ"よ、Shelleyの詩の言葉は…」
真琴:「イイのイイの、これはアタ"詩"の言葉だから^^;」


GT-BASS  2009-02-11 02:33:59  No: 33320

春来りなば…さん
有難うございます。いつも楽しみに読んでいる真琴さんと春子さんにもご登場頂けるとは...。
私が使用している「Delphiのバージョン」まで考慮して頂き感謝しております。
このお心遣いが非常に嬉しいです。

有難う御座いました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加