RubyでWMI

概要

WindowsにはWMI(Windows Management Instrumentation)という仕組みがある。 Windowsが管理しているHotFixの適用状況や、インストールされているアプリケーションの一覧などにアクセスするための仕組みらしい。

RubyのWin32OLEを使うと、WMIにもアクセスできるので、自分のPCやリモートPCのいろんな情報を取得できる。これらの情報を駆使すれば、会社でシステム管理 業務にも役立つ。

WMIの基本

たとえば、OSに関する情報を得るには、"Win32_OperatingSystem"というクラスを使えばいいことになっている。このクラスに用意されているプロパティを 使えば、OSの製品名やサービスパック名が得られる。

  01: require 'win32ole'
  02: 
  03: wmi = WIN32OLE.connect('winmgmts://')
  04: osinfo_collection = wmi.InstancesOf("Win32_OperatingSystem")
  05: osinfo_collection.each {|item|
  06:   puts "Caption =  #{item.Caption}"      # -> Microsoft Windows 7 Home Premium
  07:   puts "CodeSet =  #{item.CodeSet}"      # -> 932
  08:   puts "CSDVersion = #{item.CSDVersion}" # -> Service Pack 1
  09:   puts "OSType = #{item.OSType}"         # -> 18
  10:   puts "Version = #{item.Version}"       # -> 6.1.7601
  11: }
  

WMIについての学習方法

WMIについて、用語の正しい意味を理解するには、以下のページが大変参考になる。

WMIの各種マネージリソースで用意されているプロパティやメソッドの解説が載っている。

どんなWMIマネージリソースがあって、どんなことが調べられるかについては、サンプルを探すのがいい。

ここに載ってるサンプルでは、SQL文を使って、マネージリソースを得ている。 以下の3つは同じ意味になる。

  require 'win32ole'
  
  # VBS for Windows Management Instrumentationに載っているサンプルをRubyに移植
  locator = WIN32OLE.new('WbemScripting.SWbemLocator')
  service = locator.ConnectServer
  qfe_set = service.ExecQuery("select * from Win32_OperatingSystem")
  qfe_set.each {|item|
    puts "caption = #{item.caption}"
  }
  
  # WMI ServiceでSQL文を使って検索
  wmi = WIN32OLE.connect('winmgmts://')
  qfe_set = wmi.ExecQuery("select * from Win32_OperatingSystem")
  qfe_set.each {|item|
    puts "caption = #{item.caption}"
  }
  
  # InstancesOfを使用
  wmi = WIN32OLE.connect('winmgmts://')
  qfe_set = wmi.InstancesOf("Win32_OperatingSystem")
  qfe_set.each {|item|
    puts "caption = #{item.caption}"
  }
  

SQL文を使う場合、whereを使ってプロパティで条件を指定できるが、それで処理速度が速くなるわけじゃないので、3番目の方法を使うのがいいのではないか。

WMI Administrative Tools

WMIを使うには、「xxxという情報を得るには、yyyというクラスのインスタンスを作って、このメソッドを呼ぶ」という情報が必要。 そのようなヘルプみたいなものが、「WMI Administrative Tools」というMicrosoft製のツールだ。ダウンロードしてインストールしておこう。

このツールに含まれている、以下のツールを使用する。

WMI CIM Studio

WMIに関する各クラスで用意されているメソッドやプロパティの一覧を表示してくれる。

WMI Object Browser

自PCのWMIオブジェクトの一覧と、各プロパティの値を表示してくれる。このプロパティからどんな情報が得られるのか、確認できる。 モノによっては、情報が表示されるまで数分かかるようなものもある。

サンプルコード集

HotFixの一覧を得る

HotFixの一覧を得るには、Win32_QuickFixEngineeringというマネージリソースを利用する。

ただ、実際に実行してみると、あまり役立つ情報は得られない。KBxxxxxの番号くらい。おまけに明らかに数が少ないような気がする。 また、5行目のeachで要素を抜き出すのに結構時間がかかる。これはRubyだから、というわけじゃなく、VBでもなんでも 同じく時間がかかるもののようだ。

また、PCによってはこの方法でも、一切履歴情報が得られない。何が要因か知りたいのだが、まだよくわかってない。

  require 'win32ole'
  
  wmi = WIN32OLE.connect('winmgmts://')
  hotfix_collection = wmi.InstancesOf("Win32_QuickFixEngineering")
  hotfix_collection.each {|hotfix|
    hotfix_id = hotfix.HotFixID
    date = hotfix.InstallDate
    caption = hotfix.Caption
    description = hotfix.Description
    comments = hotfix.FixComments
    name = hotfix.name
    puts [hotfix_id, date, caption, description, comments, name].join(',')
  }
  

HotFixの情報を得るには、以下の方法の方が役に立つ。 こちらはWindowsUpdateをつかさどるサービスに接続して、そこから情報を得る方法。要は、WindowsUpdateの更新履歴を取得できる。

更新履歴に表示される順序も同じ。

  require 'win32ole'
  
  ResultDic = {
    0 => "まだ開始してない",
    1 => "実行中",
    2 => "成功",
    3 => "途中で失敗",
    4 => "完全に失敗",
    5 => "中断",
  }
  update_session = WIN32OLE.new("Microsoft.Update.Session")  # WSUSに接続
  update_searcher = update_session.CreateUpdateSearcher # IUpdateSearcher Interface
  total_count = update_searcher.GetTotalHistoryCount  # 履歴の数を求める
  history_collection = update_searcher.QueryHistory(0, total_count)  # 全ての履歴を取得
  history_collection.each {|history|
    title = history.Title
    result = ResultDic[history.ResultCode] or "未定義:#{history.ResultCode}"
    installed_date = history.Date
    puts [title, installed_date, result].join(',')
  }
  

似たようなものに、こんなのもあるんだが、数が合わない。何のためのモノなのかイマイチ不明。

  update_session = WIN32OLE.new("Microsoft.Update.Session")  # WSUSに接続
  update_searcher = update_session.CreateUpdateSearcher # IUpdateSearcher Interface
  results = update_searcher.Search("Type='Software'")   # ISearchResult Interface
  update_collection = results.Updates  # IUpdateCollection
  update_collection.each {|update|
    title = update.title
    upd_method = update.AutoSelectOnWebSites ? "推奨更新" : "その他更新"
    release_date = update.LastDeploymentChangeTime
    puts [title, upd_method, release_date].join(',')
  }
  

インストールアプリの一覧を得る

インストールされているアプリの一覧を得るには、Win32_Product というマネージリソースを利用する。

このマネージリソースは、インストールされているアプリのコレクションになっているので、ソフト名やインストールされた日付などの情報を得ることができる。

ただし、インストールされているはずなのに、この方法でひっかからないPCもある。何が原因なのかはよくわからない。

  require 'win32ole'
  
  wmi = WIN32OLE.connect('winmgmts://')
  mgres_product = wmi.InstancesOf("Win32_Product")
  mgres_product.each {|product|
    caption = product.Caption
    version = product.Version
    date = product.InstallDate
    vendor = product.Vendor
    puts [caption, version, date, vendor].join(',')
  }
  

PCの機種名やメーカー名を得る

PCの機種名やメーカー名を得るには、、Win32_ComputerSystem というマネージリソースを利用する。

  require 'win32ole'
  
  wmi = WIN32OLE.connect('winmgmts://')
  mgres_computer_system = wmi.InstancesOf("Win32_ComputerSystem")
  mgres_computer_system.each {|computer_system|
    model = computer_system.Model
    manufacture = computer_system.Manufacturer
    puts [model, manufacture].join(',')
  }
  


戻る