前回はWMIへの接続の基本を書いた。
$wmi = Win32::OLE->GetObject( "winmgmts:/root/CIMV2" ); $items = $wmi->ExecQuery( $sql );
しかし、この構文ではローカルのPC、しかも現在のユーザー資格情報で接続しようとする。別の資格情報を使ったり、他のPCの情報が欲しいときは次の構文を使う。
$locator = Win32::OLE->CreateObject( "WbemScripting.SWbemLocator" ) $wmi = $locator->connectserver( "サーバー名", "root/CIMV2", "ユーザー名", "パスワード" );
前回の例(デスクトップの壁紙のファイル名を得るスクリプト)を書き直してみよう。
#!/usr/bin/perl use strict; use warnings; use errors -with_using; use Perl6::Say; use Win32::OLE; binmode STDOUT => ":raw :encoding(cp932)"; binmode STDERR => ":raw :encoding(cp932)"; my ( $server, $user, $pass ) = @ARGV; my $sql = "SELECT * FROM Win32_Desktop WHERE Wallpaper != Null"; # UTF-8を使えるようにする # あと、警告レベルも上げる Win32::OLE->Option( CP => Win32::OLE::CP_UTF8, Warn => 3, ); my $locator = Win32::OLE->CreateObject( "WbemScripting.SWbemLocator" ); my $wmi = try { $locator->connectserver( $server, "root/CIMV2", $user, $pass ); } catch Error using { if ( /0x80041064/ ) { $locator->connectserver; } else { die; } }; my $items = $wmi->ExecQuery( $sql ); for my $i ( in $items ) { say $i->Wallpaper; }
サーバーにWindows Server 2003を指定したときの実行例1。
X:\tmp>perl test.pl 192.168.xx.xx administrator パスワード (なし) (なし) (なし) C:\WINDOWS\web\wallpaper\草原.bmp C:\Documents and Settings\user\Local Settings\Application Data\Microsoft\Wallpaper1.bmp (なし) X:\tmp>
ここではいくつかのテクニックを使っている。まずは13行目~16行目。
Win32::OLE->Option( CP => Win32::OLE::CP_UTF8, Warn => 3, );
これはWMIを使うときのおまじないみたいなものだ。CP
オプションで使う文字コードを指定し、Warn
オプションによりエラーが起きたときはちゃんとdie
するようにする。
my $wmi = try { $locator->connectserver( $server, "root/CIMV2", $user, $pass ); } catch Error using { if ( /0x80041064/ ) { $locator->connectserver; } else { die; } };
ここは以前、「use errors; のススメ」で書いたerrors.pm
のtry
~catch
構文を使っている。今回使ったconnectserver
メソッドは、ローカルPCに対して実行すると0x80041064
エラーで落ちてしまう。そのときはエラー番号を確認し、改めて引数なしで実行している。その他のエラーが起きたときはdie
する。
これで他のPCの情報も得られるようになった。後はSQL句を工夫するだけでどんな情報でも手に入る。
次回に続く。
-
ここでは「
(なし)
」という本来必要のない情報がリストアップされている。Windows7ではこのような場合Null値が現れていたので「Wallpaper != Null
」というWHERE句
で除くことが出来たのだが、同様に「Wallpaper != '(なし)'
」とやってもうまくいかなかった。文字コードの問題だろうか? ↩