Windows PowerShellWindows PowerShell のコンストラクト

Don Jones

先月は、Windows PowerShell を使って、実際にスクリプトを作成しなくても、管理タスクの解決にすぐに使用できる方法を紹介しました。Windows PowerShell は優れたインタラクティブ シェルではありますが、その強力かつ簡単なスクリプト言語を実際に利用して初めて、その機能を活用し、複雑なタスクを自動化することができます。

ただ、ちょっと考えてみてください。マイクロソフトは本当に別のスクリプト言語を必要としているのでしょうか。マイクロソフトは、何といっても、ログオン スクリプト プロセッサである KiXtart と VBScript (Visual Basic® Scripting Edition) を提供しています。しかし、この答えはイエスです。マイクロソフトは、実際に別のスクリプト言語を必要としていたのです。その理由を説明しましょう。

Windows PowerShell™ の言語は、管理者が多くのトレーニングを積まなくても利用できるようにシンプルかつ直感的であることが必要でした。また、Windows PowerShell そのものがユーザーに提供しているすべての強力な機能に対応できるように、言語には高い柔軟性も要求されました。

Windows PowerShell は、Microsoft® .NET Framework に基づいているため、そのスクリプト言語構文は .NET に近いものであることが求められました。Windows PowerShell のスクリプト言語をアセンブルする際、デザイナは必然的に非常に簡素化された C# ("C シャープ" と発音し、.NET Framework に同梱されている言語の 1 つ) の構文を選びました。どうして VBScript のような構文にしなかったのでしょうか。Windows PowerShell スクリプト言語は実際 VBScript とあらゆる点で異なるわけではありませんが、C# 構文により近づけることで、PowerShell が .NET Framework プログラミングを学ぶ際の第一歩となるようにしたのです。上のレベルの Visual Studio® に移行することに決めてから、C# アプリケーションの作成を開始しても、Windows PowerShell スクリプト構文のほとんどが移行後も役に立ちます。

Windows PowerShell スクリプト言語に限らず、どのスクリプト言語においても、最も重要な点の 1 つはそのコンストラクトです。これらの特殊な言語要素を使って、Windows PowerShell で論理比較を実行し、比較の結果に基づいて異なるアクションを実行したり、1 つ以上の命令を何度も繰り返すことができます。

論理的な考え方

論理比較は、多くのスクリプト言語コンストラクトの中心であり、Windows PowerShell も例外ではありません。比較では、基本的に 2 つの値またはオブジェクトを参照し、比較が True または False のどちらであるか評価します。たとえば、ユーザーのパスワードの有効期限が今日の日付と同じかどうかを確認するとします。その結果は、日付が同じであれば True、異なる場合は False になります。True と False は先頭の文字を大文字にしています。これらの用語は、Windows PowerShell 内で特別な意味を持つからです。

次に、Windows PowerShell 内で実行できる実際の論理比較の例を示します。

PS C:\> $a = 1
PS C:\> $b = 2
PS C:\> $a -eq $b
False

$a という名前の変数を作成し、1 の値が含まれるようにその変数を設定しました。Windodws PowerShell では、変数名の先頭にドル記号が付いているため、簡単に見分けることができます。= は、値を代入するために使用されるので、専門用語では代入演算子と呼ばれます。次に、2 つ目の変数として $b を作成し、2 の値を代入しました。その後、実際の論理比較として、Windows PowerWhell に -eq (equality) 演算子を使用して $a と $b の内容を比較するように命令しました。PowerShell は比較を実行し、2 つの値が等しくないと判断したため、False という結果を表示しています。

Windows PowerShell の演算子は、これまで使用されている他のスクリプト言語とは若干異なり、C# とも異なります。多くの言語は = 演算子を使用して等値チェックだけでなく、値の代入も実行します。Windows PowerShell では、混乱を避けるために各関数専用の演算子を使用しています。図 1 に、Windows PowerShell の比較演算子と、既に慣れ親しんでいる他の言語 (VBScript) の対応する演算子を示します。

Figure 1 PowerShell 比較演算子

演算子 名前 説明
-eq Equality (等値) 値が同じかどうかをテストします。他の言語では、等しいかどうかテストする場合、= または == が使用されます。
-ne Not Equal (次の値に等しくない) 値が等しくないかどうかをテストします。他の言語では、等しくないかどうかのテストに、<> または != が使用されます。
-gt Greater Than (次の値より大きい) ある値が他の値よりも大きいかどうかをテストします。他の言語では、> 文字が使用されます。
-lt Less Than (次の値より小さい) ある値が他の値よりも小さいかどうかをテストします。他の言語では、< 文字が使用されます。
-ge Greater Than or Equal To (次の値以上) ある値が別の値以上かどうかをテストします。VBScript および他の言語の >= と似ています。
-le Less Than or Equal To (次の値以下) ある値が別の値以下かどうかをテストします。VBScript および他の言語の <= と似ています。

これらの比較演算子には、他にも興味深い機能があります。次の比較を見てみましょう。

PS C:\> $a = "TechNet"
PS C:\> $b = "technet"
PS C:\> $a -eq $b
True

既定では、比較演算子は大文字と小文字を区別しません。つまり、先頭が大文字の "TechNet" は、"technet" と同じとみなされます。多くの管理者は大文字と小文字の区別を気にしないので、これは便利です。ただし、Windows PowerShell では、比較演算子の前に C の文字を付けることで大文字と小文字を区別した比較を実行することができます。

PS C:\> $a -ceq $b
False

同様に、Windows PowerShell が大文字と小文字を区別しない比較を実行するかどうかわからなくなった場合は、i の文字を前に付けることで大文字と小文字を区別しない比較を実行できます。

PS C:\> $a -ieq $b
True

論理比較の結果は常に 2 つの値、つまり True または Flase のいずれかになることを覚えておいてください。

決定

論理比較の作成方法を理解したら、それらをコンストラクトで使用することができます。最初に紹介するコンストラクトを使用すると、Windows PowerShell で比較に基づいた決定を行うことができます。これは If コンストラクトと呼ばれ、そのバリエーションがいくつかあります。最も単純な例を次に示します。

PS C:\> if ($a -eq $b) {
>> Write-Host "They are equal"
>> }
>>
They are equal

この例には注目すべき興味深い点がいくつかあります。最初に、この例でも変数 $a と $b にはそれぞれ "TechNet" と "technet" の値が代入されています。まず、If キーワードを使用してコンストラクトを開始しています。その後のかっこ内に、実行する論理比較を入力しています。その後に続く中かっこは、条件コード、つまり比較によって True の結果が返された場合に Windows PowerShell が実行するコードの呼び出しの開始を知らせるものです。前述の例から、この比較では True が返されることがわかっているので、実行する条件コードを予想できます。条件コードとして「Write-Host "They are equal"」と入力し、Enter キーを押します。最後に、閉じ中かっこを入力し、Enter キーを 2 回押して条件コード セクションを終了します (空の行で 2 回目の Enter キーを押すと、作成が完了し、コードを実行をできる状態であるとパーサーが判断します)。

このコンストラクトはスクリプト ファイルからは実行されていません。このコンストラクトは Windows PowerShell コマンド ラインに入力しているだけです。これは、Windows PowerShell が Windows スクリプトの中でもユニークな存在であることを表しています。スクリプトは、インタラクティブに作成できるだけでなく、ファイルに挿入して永久保存することができるのです。

開始中かっこを入力して Enter キーを押すとすぐに、Windows PowerShell には >> プロンプトが表示されました。これは、"コンストラクト内にユーザーが存在していることを認識し、コンストラクト内で実行する内容を入力できます" ということを伝えています。閉じ中かっこを入力し、Enter キーを 2 回押した後、Windows PowerShell では直ちにコンストラクトが実行されて、その論理比較が True であることが確認され、条件コードが実行されます。これは、通常のプロンプトに戻る前に、"They are equal" が表示されていたことからわかります。Windows PowerShell を使用してスクリプトをインタラクティブに作成すると、それらをより永続的なスクリプトにアセンブルする前にコードをすばやくテストできるので、学習とデバッグの両方を簡単に行うことができます。

Windows PowerShell では、Enter キーを押すなどの動作を必ず行う必要はありません。たとえば、次の例は、前の例と内容的には同じです。

PS C:\> if ($a -eq $b) { Write-Host "They are equal" }
They are equal

この例はすべて 1 行に入力しているため、Windows PowerShell は特殊な >> プロンプトを表示する必要はありません。行の最後に Enter キーを押すと、コンストラクトが単純に実行されるだけです。Windows PowerShell は、コンストラクトが実行できる状態であることをどうやって知るのでしょうか。この場合、閉じ中かっこが入力された時点で完了ということを意味します。

If コンストラクトには他のバリエーションがあることは前にも説明しました。次の例は、シェルではなく、PS1 スクリプト ファイルに表示される完全な例です。

if ($a -eq $b) {
  Write-Host "They are equal"
} elseif ($a -lt $b) {
  Write Host "One is less than the other"
} else {
  Write Host "One is greater than the other"
}

コンストラクトは、If キーワードを使用して同じように開始されています。ただし、比較結果が False であった場合は、Elseif キーワードを使用して別の比較を実行することを指定しています。その 2 番目の比較結果も False だった場合は、最後のキーワード Else で、最後のコードが実行されます。

繰り返しの実行

Windows PowerShell には、比較結果が True または False になるまでコードを何度も実行するための 1 組のコンストラクトがあります。プログラマはこれらを loop コンストラクトと呼んでいます。最も有用な loop コンストラクトの 1 つを使用すると、コレクション内のオブジェクトを列挙し、各オブジェクトに対して 1 行以上のコードを実行することもできます。このコンストラクトは foreach コンストラクトと呼ばれます。このコンストラクトの例を次に示します。

PS C:\> $names = get-content "c:\computers.txt"
PS C:\> foreach ($name in $names) {
>> Write-Host $name
>> }
>>
don-pc
testbed

最初に Windows PowerShell Get-Content cmdlet に対して c:\computers.txt ファイルのコンテンツを取得するように命令しています。このファイルは著者自身が作成したファイルで、各行に 1 つのコンピュータ名が含まれています。Windows PowerShell は各行を 1 つのオブジェクトとして扱うため、ファイルは必然的にそれらのオブジェクトを含むコレクションになります。コレクションは変数 $names になります。foreach キーワードを使い、ループが実行されるたびに現在のオブジェクトを表す変数 $name を使用して Windows PowerShell で $names コレクションを列挙するように命令しています。ループ コードは中かっこの中にあります。そのため、ファイル内の各名前について、その名前がコマンド ラインに出力されます。また、コンストラクトの後の出力を確認すると、Windows PowerShell が実行した正確な内容がわかります。これは、管理スクリプトにおける明確な利点を示しています。たとえば、サーバー名の一覧を簡単に作成でき、Windows PowerShell で各リストから情報を取得できるのです。

実際のコンストラクト

ここでは、論理比較、If コンストラクトおよび foreach コンストラクトを使って、実際に何か役に立つことを実行してみましょう。サーバーのセットにおける Messenger サービスのステータスをすばやくチェックしたいと思います。サービスはほとんどのサーバーで停止されることが予想されますが、Windows PowerShell では、サービスが予想された状態になっているサーバーをすべてリストする作業は行いません。必要なのは、Messenger サービスが実際に開始されているサーバーをリストすることです。それらのサーバーでなんらかの作業を実行する必要があるからです。

Windows PowerShell Get-Service cmdlet を使用すれば、ローカル コンピュータに必要な情報を取得できることはわかっていますが、実際の目標であるリモート コンピュータにはアクセスできません。この場合、Get-WMIObject cmdlet を使って Windows Management Instrumentation (WMI) 経由で同じ情報にアクセスし、リモート コンピュータを使用することができます。この場合のスクリプトを次に示します。

$names = get-content c:\computers.txt
foreach ($name in $names) {
  $svc = get-wmiobject win32_service '
   -computer $name -filter "name='messenger'"
  if ($svc.started -eq $True ) {
    write-host "$name has Messenger running"
  }
}

3 行目の ' という文字に注目してください。この文字は、Windodws PowerShell に、次の行が継続行であることを知らせるものです。これは、行全体を折り返さないとマガジンに収まらないような場合に便利です。また、If コンストラクトが $svc.started to $True を比較していることにも注目してください。変数 $True は、ブール型の True 値を表す、Windows PowerShell の特殊な変数です (比較変数 $ False はブール型の False を表します)。実際は、次のように若干簡素化して表すことができます。

$names = get-content c:\computers.txt
foreach ($name in $names) {
  $svc = get-wmiobject win32_service '
   -computer $name -filter "name='messenger'"
  if ($svc.started) {
    write-host "$name has Messenger running"
  }
}

前にも説明したように、If コンストラクトの条件は単純に True または False になる必要があります。通常、2 つの値を比較すると、このスクリプトの最初のバージョンで示したように、True または False を取得できます。ただし、Started プロパティは True または False のいずれかであるため、実際には True または False と比較する必要はありません。

役に立つツール

これで、ジョブを実行する際に、コンストラクトを利用する簡単で役に立つ管理ツールを使用できるようになりました。Windows PowerShell にインタラクティブ入力する場合でも、PSI ファイルに保存して簡単に再利用する場合でも、このツールはさまざまなコンピュータ上のサービスのステータスをチェックすることができる便利なツールであり、コンストラクタのデモは管理タスクを自動化するうえで役立ちます。

Don JonesSAPIEN Technologies のプロジェクトおよびサービスの責任者であり、『Windows PowerShell: TFM』(SAPIEN Press、2006) の共著者でもあります。Don に対するお問い合わせについては、彼の Web サイト (ScriptingAnswers.com)(英語) を参照してください。

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