【Perl, Windows】WMIに接続する(応用編)


前回は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.pmtrycatch構文を使っている。今回使ったconnectserverメソッドは、ローカルPCに対して実行すると0x80041064エラーで落ちてしまう。そのときはエラー番号を確認し、改めて引数なしで実行している。その他のエラーが起きたときはdieする。

これで他のPCの情報も得られるようになった。後はSQL句を工夫するだけでどんな情報でも手に入る。

次回に続く。


  1. ここでは「(なし)」という本来必要のない情報がリストアップされている。Windows7ではこのような場合Null値が現れていたので「Wallpaper != Null」というWHERE句で除くことが出来たのだが、同様に「Wallpaper != '(なし)'」とやってもうまくいかなかった。文字コードの問題だろうか? 

コメントを残す