WMIを使ってコーデックの一覧を得るスクリプト。かなり煩雑で独自表記っぽくなってるけど、これもMooseの勉強の一環ってことで。コマンドプロンプトからperl codec.pl
とすると次のような結果が得られる。
C:\> perl codec.pl No.1 Manufacturer: Microsoft Corporation Name: C:\Windows\system32\MSRLE32.DLL Path: \windows\system32\ Version: 6.1.7600.16490 Caption: c:\windows\system32\msrle32.dll Drive: c: Extension: dll FileType: Application Extension Group: Video CreationDate: 2010/02/11 16:41:07 InstallDate: 2010/02/11 16:41:07 LastModified: 2009/12/19 18:47:46 No.2 Manufacturer: None Name: C:\Windows\system32\FF_ACM.ACM Path: \windows\system32\ 〜以下省略〜
表示する情報を制限したり、管理者権限のあるユーザー名とパスワードがわかれば、他のPCにアクセスしてリストを取り出すこともできる。
C:\> perl codec.pl --server コンピューター名 --user ユーザー名 --password パスワード --prop Name --prop Manufacturer No.1 Name: C:\Windows\system32\MSRLE32.DLL Manufacturer: Microsoft Corporation No.2 Name: C:\Windows\system32\FF_VFW.DLL Manufacturer: None No.3 Name: C:\Windows\system32\FRAPSV64.DLL Manufacturer: Beepa P/L 〜以下省略〜
使っているテクニックについては、日を改めて説明しよう。(一度に書いたらネタが無くなるしね!)
codec.pl
#!/usr/bin/perl package Me; use utf8; use errors -with_using; use Moose; use MooseX::AttributeHelpers; with "MooseX::Getopt"; use Win32::OLE qw! in !; # 日付文字列の表示に必要 use Win32::OLE::Variant; binmode STDOUT => ":raw :encoding(cp932)"; binmode STDERR => ":raw :encoding(cp932)"; # カラー表示するか否か has color => ( is => "ro", isa => "Bool", default => 0 ); # 表示するプロパティ一覧 has prop => ( is => "ro", isa => "ArrayRef", auto_deref => 1, default => sub { [ qw! Manufacturer Name Path Version Caption Drive Extension FileType Group CreationDate InstallDate LastModified ! ] } ); # サーバー名 has server => ( is => "ro", isa => "Str", default => "localhost" ); # ユーザー名 has user => ( is => "ro", isa => "Str", default => "administrator" ); # パスワード has password => ( is => "ro", isa => "Str", default => "" ); # カウンター has _counter => ( metaclass => "Counter", default => 1 ); # 画面表示に使うprintf文字列 has _pString => ( is => "ro", isa => "Str", lazy_build => 1 ); sub _build__pString { my $self = shift; my $str = ""; $str .= "\e[1;32m$_: \e[m%s\n" for $self->prop; $str .= "\n"; if ( $self->color ) { # コンソールに色を付ける require Win32::Console::ANSI; } else { $str =~ s/\e.*?m//g; } $str; } # WMIオブジェクト has _wmi => ( is => "ro", isa => "Object", lazy_build => 1 ); sub _build__wmi { my $self = shift; # UTF-8を使えるようにする # あと、警告レベルも上げる Win32::OLE->Option( CP => Win32::OLE::CP_UTF8, Warn => 3, ); my $namespace = "root/CIMV2", my $locator = Win32::OLE->CreateObject( "WbemScripting.SWbemLocator" ); try { $locator->connectserver( $self->server, $namespace, $self->user, $self->password ); } catch Error using { $locator->connectserver; }; } # 日付変換オブジェクト has _wbemDateTime => ( is => "ro", isa => "Object", default => sub { Win32::OLE->CreateObject( "WBemScripting.SWbemDateTIme" ) } ); # メインルーチン sub run { my $self = shift; my $items = $self->_wmi->ExecQuery( "Select * From Win32_CodecFile" ); for my $i ( in $items ) { printf "No.%d\n", $self->_counter; printf $self->_pString, map { my $item = $i->$_; if ( defined $item ) { $item =~ /\d{14}\.\d{6}\+\d{3}/ and $item = $self->_getDate( $item ); $item; } else { "None"; } } $self->prop; $self->inc__counter; } } # 日付文字列変換関数 sub _getDate { my $self = shift; $self->_wbemDateTime->{value} = shift; $self->_wbemDateTime->GetVarDate; } __PACKAGE__->meta->make_immutable; package main; Me->new_with_options->run;