WMIのWin32_Printerクラス

WMIのWin32_Printerクラス

VBAでプリンタまわりを操作したいなあと思って、あれこれ調べていると、「WMI(Windows Management Instrumentation)」というものを使うという道があることがわかった。

そうしょっちゅう使うわけでもないが、覚書として記しておくことにする。

ちなみに、Shellを使う方法については、

akashi-keirin.hatenablog.com

コチラをどうぞ。

目次

お世話になったサイト

いろいろ調べているうちにたどり着いたのは、

www.wmifun.net

こちら。

このページには、次のサンプルコードが掲載されている。

Option Explicit

'WMIにて使用する各種オブジェクトを定義・生成する。'
Dim oClassSet
Dim oClass
Dim oLocator
Dim oService
Dim sMesStr

'ローカルコンピュータに接続する。'
Set oLocator = WScript.CreateObject("WbemScripting.SWbemLocator")
Set oService = oLocator.ConnectServer
'クエリー条件を WQL にて指定する。'
Set oClassSet = oService.ExecQuery("Select * From Win32_Printer")

'コレクションを解析する。'
For Each oClass In oClassSet

sMesStr = sMesStr & "プリンタの名前: " & oClass.Caption & vbCrLf & _
"プリンタのドライバー名: " & oClass.DriverName & vbCrLf & _
"プリンタのポート: " & oClass.PortName & vbCrLf & _
"デフォルトプリンタか?: " & CStr(oClass.Default) & vbCrLf & vbCrLf

Next

MsgBox "プリンタに関する情報です。" & vbCrLf & vbCrLf & sMesStr

'使用した各種オブジェクトを後片付けする。'
Set oClassSet = Nothing
Set oClass = Nothing
Set oService = Nothing
Set oLocator = Nothing
WMI Fun!! 様より

詳しいことはよくわからんが、WbemScriptingというライブラリにあるSWbemLocatorクラス(?)から順に下位のクラスを取得していっている模様。

上掲ソースコードはVBSのものだが、VBEで[ツール]→[参照設定]で、Microsoft WMI Scripting V1.2 Libraryにチェックを入れれば、オブジェクト ブラウザーである程度まで中身を見ることができる。

上掲コードの

Set oLocator = WScript.CreateObject("WbemScripting.SWbemLocator")

で変数oLocatorにぶち込まれるのは、たぶん、

f:id:akashi_keirin:20201219185250j:plain

このWbemScripting.SWbemLocatorクラスのインスタンス

んで、

Set oService = oLocator.ConnectServer

こいつによって変数oServiceにぶち込まれるのは、たぶん、

f:id:akashi_keirin:20201219185252j:plain

このSWbemServicesオブジェクト。

さらに。

Set oClassSet = oService.ExecQuery("Select * From Win32_Printer")

で、SWbemServicesオブジェクトのExecQueryメソッドによってWin32_Printerというオブジェクトを取得し、変数oClassSetにぶち込んでいる(のだと思う)。

変数の名前からして、こいつは、

f:id:akashi_keirin:20201219185255j:plain

SWbemObjectSetというオブジェクトだと思う。

あとは、For ~ Eachを使ってSWbemObjectSetからSWbemObject(インストールされているプリンタ一つ一つに対応)を取り出して、そのプロパティの値を取得している(のだと思う)。

んで、このとき一つ一つ取り出されるオブジェクトは、

f:id:akashi_keirin:20201219185258j:plain

SWbemObjectだろう。

VBAに移植する

先に引用したコードを、VBA向けに移植する。

せっかくMicrosoft WMI Scripting V1.2 Libraryを参照設定済みなので、アーリー・バインディング方式でコーディングすることとしよう。

上掲コードではメッセージボックスに表示するようにしているが、うっとうしいので、イミディエイト・ウィンドウに出力するようにしているので、あしからず。

リスト1 標準モジュール
Private Sub test01()
  Dim currLocator As WbemScripting.SWbemLocator
  Dim tgtServices As WbemScripting.swbems
  Dim tgtClassSet As WbemScripting.SWbemObjectSet
  'ローカルコンピュータに接続する。'
  Set currLocator = New WbemScripting.SWbemLocator
  Set tgtServices = currLocator.ConnectServer
  'クエリー条件を WQL にて指定する。'
  Set tgtClassSet = tgtServices.ExecQuery("SELECT * FROM Win32_Printer")
  
  Dim tgtClass As WbemScripting.SWbemObject
  Dim tmp As String
  'コレクションを解析する。'
  For Each tgtClass In tgtClassSet
    With tgtClass
      tmp = "プリンタの名前: " & .Caption & vbCrLf & _
            "プリンタのドライバー名: " & .DriverName & vbCrLf & _
            "プリンタのポート: " & .PortName & vbCrLf & _
            "デフォルトプリンタか?: " & CStr(.Default) & vbCrLf & vbCrLf
    End With
    Debug.Print tmp
  Next

  '使用した各種オブジェクトを後片付けする。'
  Set tgtClass = Nothing
  Set tgtClassSet = Nothing
  Set tgtServices = Nothing
  Set currLocator = Nothing
End Sub

残された課題

さて。上掲リスト1を実際にVBEで入力してみるとわかることなのだが、For ~ Eachループの中、すなわち、個別のプリンタを指し示すオブジェクト(変数tgtClassにぶち込まれている)については、入力補完が効かない。

もし、これが不便だと感じるのならば、たとえばSWbemObjectをラップしたクラスを作って、Win32_Printerクラスのプロパティ・メソッドを自力で実装する、という手もあるかも知れない。

www.wmifun.net

ここを見たらできるはず。

おわりに

まあ、WMIを以てしても、プリンタ名の「on ~」の部分は取得できないっぽいので、そこまでムキになることもないかな。

写経の一環としてやってみたら面白いかも知れませんけど。