Windows PowerShellスクリプトを使用しないで作業する

Don Jones

カンファレンス、パブリック ニュースグループ、あるいは私個人のサイトであれ、Windows PowerShell について話すたびに、必ず Windows PowerShell の学習は "先送りする" と話す管理者に会います。なぜでしょうか。最も一般的な理由は、

"スクリプトの作成方法を今すぐに学習する時間がない"、というものです。

これは、よくある意見です。私たち管理者は忙しく、新しいテクノロジを学習するための自由な時間はあまりないというのが実情です。しかし私たちは常に前進して、Windows Vista®、Windows Server® 2008、Exchange Server 2007 などの新しいソフトウェアを学び、私たちの仕事にとって重要なテクノロジを熟知していなければなりません。Windows PowerShell™ は、これらのテクノロジの大きな部分を占めています。

Windows PowerShell のスクリプトの学習を先延ばしにする別の理由として管理者からよく聞くのは、私の同僚の管理者が言うように、「プログラマになることへの懸念」です。なるほど、それなら私が何かお役に立てるかもしれません。Windows PowerShell でコードをまったく記述することなく、本当にすばらしいことが実行できることを知って驚かれることでしょう。

パイプラインについて

私は以前、Windows PowerShell で使用される、極めて柔軟で強力なオブジェクト指向のパイプラインについて記事を書いたことがあります ("オブジェクト指向" という言葉から、私の話がプログラマの世界に向かっているのではないかと疑われるかもしれませんが、どうか最後までお読みください)。私がパイプラインについて気に入っている点の 1 つは、対話的に使用できるということです。すぐに結果が表示され、必要な情報を正確に得られるように、出力結果を容易に調整することができます。たとえば、数台のリモート コンピュータにおける空きディスク領域の一覧を取得するとします。それらのコンピュータの名前は C:\Computers.txt というテキスト ファイルに記述されています。これはコンピュータ名が 1 行に 1 つずつ記述された単純なテキスト ファイルであり、データベースのように複雑ではありません。

まず、この空きディスク領域の情報をローカル コンピュータから取得できるかどうかを確認します。1 台のコンピュータ上で取得可能であることがわかれば、複数のコンピュータ上でタスクを実行するのは非常に簡単です。お気づきかもしれませんが、ここではスクリプトは必要ありません。すべてをシェルで対話的に実行し、Enter キーを押すとすぐに結果が得られます。

このようなタスクのヒントをお教えします。リモート コンピュータからインベントリ管理情報の一覧を取得する場合は、おそらく Windows® Management Instrumentation (WMI) を使用することになるでしょう。この例では、WMI を使用する必要があること以外、私は何も知らないとします。そのため、Live Search にアクセスして、検索用語として「windows wmi free disk space」と入力します。いくつかの結果が表示され、その抜粋に "Win32_LogicalDisk" という語句が含まれています。これは WMI クラスのように見えます。これが私が探しているものかもしれません。私は、これらの検索結果のいずれもクリックせずに、代わりに、新しい検索用語として「Win32_LogicalDisk」と入力します。検索結果の一番上に、MSDN® サイト上の Win32_LogicalDisk のドキュメント ページ (msdn2.microsoft.com/aa394173.aspx) のリンクが表示されます。そのページにアクセスすると、このクラスのプロパティの 1 つが FreeSpace であることがわかります。これは期待できそうです。

コマンドレットを検索する

次に、WMI クラスのプロパティを取得するコマンドレットを検索する必要があります。Windows PowerShell の注目すべき特性の 1 つは、すばらしい自己検出機能が組み込まれているということです。つまり、シェルを使用して、シェル自身の機能に関する情報を簡単に得ることができます。「Help *wmi*」と入力すると、WMI の操作に関する情報が表示されます。図 1 のような結果が表示されます。Gwmi はエイリアス、Get-WMIObject はそのエイリアスが指すコマンドレットです。基本的には、これら 2 つの方法で同じ機能にアクセスできます。どちらを使用するか決めるのに悩む必要はありません。実行結果は同じなので、私は入力する文字数が少ない Gwmi を使用します。

図 1 WMI の操作に関する情報

図 1** WMI の操作に関する情報 **(画像を拡大するには、ここをクリックします)

PS C:\> gwmi win32_logicaldisk

Windows PowerShell では大文字と小文字が区別されません。管理者には Shift キーを押すなどの細かい作業を行う時間がないことを知っているからです。

図 2 に示すように、このコマンドの結果には、5 つのローカル ドライブすべてと、それらのドライブの FreeSpace プロパティがバイト単位で表示されています。また、これらの各ドライブの DriveType プロパティも表示されており、コンピュータ上に 2、3、および 5 のドライブの種類があることがわかります。

図 2 すべてのローカル ドライブとその FreeSpace プロパティ

図 2** すべてのローカル ドライブとその FreeSpace プロパティ **(画像を拡大するには、ここをクリックします)

今月のコマンドレット

Get-Content を使用して、テキスト ファイルの内容を読み取ったことがあるかもしれませんが、このコマンドレットは、ファイルの各行を [string] オブジェクトとして扱います。他のコマンドレットで使用できるように、それらのオブジェクトをパイプラインに渡します。ただし、Get-Content には、柔軟性を向上させるオプションが多数用意されています。たとえば、–readCount パラメータを使用すると、パイプラインに一度に渡す [string] オブジェクトの数を指定できます (既定ではすべてのオブジェクト)。また、–totalCount パラメータを使用すると、ファイルから読み取る行の合計数を指定できます。これらのパラメータは両方とも、パフォーマンス上の理由でファイル全体を一度に処理したくない場合など、非常に大きなファイルを操作するときに便利です。

他にも便利なパラメータがあります。–encoding パラメータです。このパラメータを使用すると、Unicode、ASCII、UTF7、UTF8 などのさまざまなエンコードの種類のファイルを正しく読み取ることができます。サポートされているすべてのエンコードの種類の一覧を表示するには、"help gc" (gc は Get-Content のエイリアス) を実行します。**

データを調整する

この時点で 2 つの問題があります。1 つ目の問題は、私に必要なのは FreeSpace だけで、他のすべてのプロパティは必要ないということです。2 つ目の問題は、ローカル ハード ディスクの空き領域のみ知る必要があり、光学式ドライブ、リムーバブル ドライブ、またはネットワーク ドライブの空き領域を知る必要はないということです。この場合、おそらく DriveType プロパティがドライブを区別するのに役立つでしょう。先ほどの Web ブラウザに戻って、ドキュメントにそれぞれの DriveType の値が何を表すかを説明した表が含まれているのを確認します。必要なのは DriveType が 3 (ローカル ハード ディスク) のドライブだけです。今までにやったことがないので、Gwmi コマンドで何らかのフィルタが可能かどうかを確認することにしました。"Help Gwmi -full" を実行すると、コマンドの動作に関する詳細情報といくつかの例が表示されます。–filter という便利そうなパラメータを見つけたので、これを使って実行してみます。

gwmi win32_logicaldisk -filter "drivetype = 3"

うまくいきました。ドライブの一覧には、ローカルの固定ディスクのみ表示されています。これで 2 つ目の問題は解決されました。次は、必要ないプロパティを取り除いて、1 つ目の問題を解決する必要があります。

Get-Command を実行して Windows PowerShell のすべてのコマンドレットの一覧を表示し、最終的に Select-Object を見つけました。Select-Object の説明には、"Select specified properties of an object or set of objects." (オブジェクトまたはオブジェクトのセットの指定したプロパティを選択します。) とあります。次のコマンドを試します。

gwmi win32_logicaldisk -filter "drivetype = 3" | select freespace

Gwmi の結果を Select (Select-Object のエイリアス) にパイプすることで、必要なプロパティのみ取得できます。さて、ここで困ったことが起きました。表示されたのは数字の一覧なので、これはあまり良い結果ではありません。これではどのドライブにどれだけの空き領域があるかわかりません。そのため、再びドキュメントに戻って、DeviceID プロパティにドライブ文字が含まれることを確認しました。すぐにコマンドを改訂して再実行します。

gwmi win32_logicaldisk -filter "drivetype = 3" | select deviceid,freespace

完璧です。一覧には 2 つのプロパティしか表示されていないので、シェルでは情報が見栄えの良い表になります。Windows PowerShell が一覧と表の使用を選択する場合については、来月説明します。

計算する

空き領域に関する情報は取得できましたが、バイト単位であるため、MB や GB などの単位ほど便利ではありません。おそらく、FreeSpace プロパティ自体は必要ではなく、FreeSpace プロパティに基づいて計算された値の方が必要でしょう。ForEach-Object コマンドレット (または % などの多くのエイリアス) が役に立ちます。このコマンドレットでは、特殊な変数 $_ を使用して、現在の論理ディスクを参照できます。また、各ディスクのプロパティに個別にアクセスして、計算を行うこともできます。改訂したコマンドを次に示します。

gwmi win32_logicaldisk -filter "drivetype = 3" | % { $_.deviceid; $_.freespace/1GB }

ここでは、Select を削除して、ForEach-Object のエイリアス (%) で置き換えただけです。この ForEach-Object コマンドレットに必要なのは、コマンドレットが取得した各 Win32_LogicalDisk に対する処理を指定することです。そのため、DeviceID プロパティを取得して、出力結果が GB で得られるように、FreeSpace プロパティを 1 GB で割ることを指定しました。Windows PowerShell は KB、MB、および GB の意味を "知っています"。

複数のコンピュータ

これで、この作業を 1 台のコンピュータに対して実行したので、次は複数のシステムに対して実行します。私は、テキスト ファイルの内容を取得する方法は知っています。Type コマンドを使用して MS-DOS® の場合と同じ方法で取得できますが、Windows PowerShell では、Type は実は Get-Content のエイリアスです。

Type c:\computers.txt

必要なのは、これらの各コンピュータについて、既に調べた WMI コマンドを実行することです。"それぞれについて" (for each one) という語句から、ForEach-Object というコマンドレットを思い出すでしょう。それでは、家庭向けのテレビ番組でよく言われるように、すぐにお見せしましょう。次の最終的なコマンドをご覧ください。

type c:\computers.txt | % { $_; 
gwmi –computername $_ win32_logicaldisk -filter "drivetype=3" | % { $_.deviceid; $_.freespace/1GB} }

ぞっとするでしょう。コマンドレット名ではなく、エイリアスだけを使用したため、読みにくくなっています。しかし、少しずつ見ていくと、簡単なものです。

  • まず、テキスト ファイルの内容を "Type" で参照しています。
  • その内容を ForEach-Object にパイプします。
  • ForEach-Object は、$_ 変数を使用して現在の項目を出力します (現在のコンピュータ名です)。
  • 次に、ForEach-Object は、私の WMI コマンドを実行します。その WMI コマンドは、別の ForEach-Object を呼び出します。

これらのエイリアス名をコマンドレット名に展開すると、わかりやすいかもしれません。同じコマンドを次に示します。ただし、今回はエイリアスではなくコマンドレット名を正確に記述し、コマンドをそれぞれ別の行に分けているので、各セクションを容易に調べられるでしょう。

Get-Content C:\Computers.txt | 
ForEach-Object { 
 $_; Get-WMIObject –computername $_ 
Win32_LogicalDisk -filter "DriveType=3" | 
 ForEach-Object { 
 $_.DeviceID; $_.FreeSpace/1GB
 }
}

出力結果は、魅力的ではありませんが、実用的です。図 3 に示します。

図 3 最終結果

図 3** 最終結果 **(画像を拡大するには、ここをクリックします)

スクリプトの作成は必要ない

このウォークスルーのポイントは、スクリプトを作成しなくても Windows PowerShell を使用できることを示すことです。また、このようないくつかの例と、Windows PowerShell に関するちょっとした調査により、目的のタスクを達成するのに必要な情報の一部を、実際に見つけることができます。

つまり、これからは Windows PowerShell の時代だということです。Windows PowerShell の学習を今すぐ始めてみてはいかがでしょうか。学習すれば、Windows PowerShell なしで今までどのようにやってきたか不思議に思うことさえあるかもしれません。スクリプトという言葉のせいで、取り組むのをためらわないでください。

Don Jones は SAPIEN Technologies のリード スクリプト グルで、ScriptingTraining.com のインストラクタです。Don に対するお問い合わせについては、彼の Web サイト (ScriptingAnswers.com) を参照してください。

© 2008 Microsoft Corporation and CMP Media, LLC. All rights reserved; 許可なしに一部または全体を複製することは禁止されています.