Windows PowerShell 入門(3)-スクリプト編
これまでの記事
対象読者
- Windows PowerShellでコマンドレット操作ができる方(基礎編に書いてある程度のことが理解できていること)
- 何らかのプログラミング経験があればなお良い
必要環境
- Windows PowerShell
スクリプトの直接入力
PowerShellにおけるスクリプトは、コマンドレット、変数、パイプ、ifやforといった制御構文を組み合わせて使用します。
では、まず簡単なスクリプトをコンソールウィンドウに直接書いてみましょう。
Windows PowerShellを起動し、下記コードを入力してください。下記コードの最後の}
を入力したら[Enter]キーを2回押します。スクリプトの入力が完了し、結果が表示されます(コンソールウィンドウ上でスクリプトを記述している間は1番左側に>>
が表示されます。このとき[Enter]キーを2回続けて入力すると、スクリプトの入力を完了し、そこまで書いていたコードを実行します。途中で入力を間違えた場合は[Ctrl]キー+[C]キーで中断することができます)。
PS C:\Work> if ( Test-Path "Test.txt" ) >> { >> Write-Host "Test.txtは存在します" >> } >> else >> { >> Write-Host "Test.txtは存在しません" >> } >>
このコードは、カレントディレクトリに対してTest.txt というファイルの存在を確認し、存在した時と存在しない時とで表示するメッセージを変えています。
少し補足説明をします。まずif
ですが、
if (条件式) { }
のように記述します。
ifは( )
の中に記述した条件式が満たされると、すぐ下の{
から}
までに書かれたコードを実行します。条件を満たさなかった場合はelse
を実行します。
- Test-Pathコマンドレット
- Write-Hostコマンドレット
よって今入力したスクリプトは、カレントディレクトリに「Test.txt」ファイルが存在すれば、「Test.txtは存在します」という文字列を、ファイルが存在しなければ「Test.txtは存在しません」という文字列を表示します。
このようにPowerShellでは、コンソールウィンドウ上で直接スクリプトを実行することが可能です。しかし決まり切ったスクリプトなどは、毎回コンソールウィンドウで入力するのは面倒です。PowerShellでは、スクリプトをファイルに保存して何度でも利用できるように設計されています。
では、スクリプトファイルはどのように作成したらいいのでしょうか。
スクリプトファイルの作成
PowerShellにおけるスクリプトファイルは、拡張子が「.ps1」のテキストファイルです。テキストファイルなので、メモ帳などのテキストエディタで作成することが可能です。
では、先ほどのコードをテキストエディタで入力し、「sample1.ps1」と名前を付けて保存しましょう(可能であれば「C:\Work」というフォルダを作成し、ここへ保存してください。以降このフォルダを使用して説明します。任意のフォルダへ保存する場合は適宜読み替えてください)。
if ( Test-Path “Test.txt” ) { Write-Host "Test.txtは存在します" } else { Write-Host "Test.txtは存在しません" }
スクリプトファイルの実行とセキュリティ
従来のスクリプティング環境のほとんどは、作成したスクリプトファイルをダブルクリックで実行することができました。しかしPowerShellでは、ダブルクリックでは実行されないように設計されています。これは簡単に実行できることで悪意のあるスクリプトファイルから身を守ることができるようへの配慮からです。
ためしに「sample1.ps1」をダブルクリックしてみてください。メモ帳で「sample1.ps1」が開かれるのではないでしょうか? スクリプトに使用される「.ps1」という拡張子がPowerShellに関連づけられていないため、このような動作になります。
PowerShellでは、スクリプトファイルは明示的に実行する必要があります。
まずはコンソールウィンドウで、
cd C:\Work
と入力し、ディレクトリを移動します。次に、
sample1.ps1
と入力し[Enter]キーを押してみてください。
まだエラーが発生してしまいます。このように実際にはスクリプトファイル名を入力するだけでは不十分です。PowerShellでは、スクリプトファイルの実行は絶対パスで指定するか、カレントディレクトリのファイルの場合は先頭に./
を付けて実行します。
では、なぜこんな面倒くさいことをしなければならないのでしょうか? 実はスクリプトの実行は拡張子を省略して入力できるのですが、拡張子を省略すると、既存のコマンドレットと同名のファイル名を付けた場合には、自作のスクリプトと既存のコマンドレットの区別ができなくなってしまいます。これはコマンドの乗っ取りと呼ばれます。
例えば「Get-Command.ps1」という名前のファイルがあったとします。これを、
Get-Command[Enter]
で実行可能だとしたらどうでしょう?
既存のGet-Commandコマンドレットとの区別がつかなくなりますし、ましてやこのスクリプトがファイルを勝手に削除してしまうようなスクリプトだとしたら大変です。
このような背景から、PowerShellでのスクリプト実行は絶対パス、またはカレントディレクトリのファイルの先頭に./
を付けて実行する仕組みとなっています。
これで、スクリプトの実行方法についてはわかりました。しかし、このままでは実行できません。PowerShellは、既定ではスクリプトの実行が許されていないからです。
コンソールウィンドウに、
Get-ExecutionPolicy
と入力し[Enter]キーを押してください。Restrictedと返ってきたのではないでしょうか? このコマンドレットは現在の実行ポリシーの設定を確認することができます。
実行ポリシーには以下の4つがあります。
実行ポリシー | 説明 |
Restricted | すべてスクリプトの実行を禁止 |
AllSigned | すべてのスクリプトに証明書を要求 |
RemoteSigned | インターネットからダウロードしたスクリプトに証明書を要求 |
Unrestricted | すべてのスクリプトの実行を許可 |
現段階では、自分のPCにあるスクリプトファイルが実行できれば良いので、実行ポリシーをRemoteSigned
に設定しましょう。Set-ExecutionPolicy
コマンドレットで実行ポリシーを変更することができます(OSがWindows Vistaの方は、Windows PowerShellを管理者として実行していないとこのコマンドレットを使用することができないので注意してください)。
Set-ExecutionPolicy RemoteSigned
と入力し[Enter]キーを押してください。これでやっとスクリプトファイルを実行できるようになりました。
では、「sample.ps1」を実行してみましょう。コンソールウィンドウで、
./sample1.ps1
と入力し[Enter]キーを押してください。
「C:\WorkにTest.txt」が存在すれば「Test.txtは存在します」を、存在しなければ「Test.txtは存在しません」と表示されるはずです(Test.txtを作成したり、削除したりして動作を確認してみてください)。
スクリプトファイルのエラー修正
残念ながら、先ほどのスクリプトを実行した結果、赤字でメッセージが表示されてしまった方もいるのではないでしょうか? これは、作成したスクリプトファイルにエラーがあることを示しています。
試しにわざとif文の最初の{ ~ }
までのWrite-HostをWrite-Hos(Hostのtを削除して)と書き換えて実行してみましょう(実験する場合Test.txtを準備してから行ってください)。
if ( Test-Path "Test.txt" ) { Write-Hos "Test.txtは存在します" } else { Write-Host "Test.txtは存在しません" }
この状態で実行してみると下記のようになるかと思います。
これはどういう意味でしょうか? 1つ1つ説明したいと思います。
用語 'Write-Hos'は、コマンドレット、関数、操作可能なプログム、 またはスクリプト ファイルとして認識されません。用語を確認し、 再試行してください。
これはまさしく書いてあるとおりで、Write-Hosというものがない(認識できない)ことを意味しています。
発生場所 C:\Work\sample1.ps1:3 文字:12 + Write-Hos <<<< "Test.txtが見つかりました"
これはエラーが発生した場所(ファイル)を示しています。今回実行したファイルは「C:\Work」に作成した「sample1.ps1」というファイルを実行してエラーが発生したので、「C:\Work\sample1.ps1」となっています。そのとなりの3 文字:12
は3行目の12文字目がおかしいということを意味しています。
このように、メッセージからエラー箇所を特定し修正を行います。
スクリプトファイルへ値を渡す
PowerShellでは外部からスクリプトファイルへ値を渡すことが可能です。ためしに下記をテキストエディタで入力し、「sample2.ps1」として保存してください。
Write-Host $args[0]
このコードについて説明します。
まずWrite-Host
コマンドレットですが、これはWrite-Hostの右側に書かれたものをコンソールウィンドウへ表示します。
次に$args
ですが、これは自動変数と呼ばれている変数で、外部から受け取った値はこの変数に代入されることが決まっています(この変数はPowerShellで予約済みの変数のため、この名前で変数を作成することはできません)。
$argsは配列変数となっており、いくつでも外部から値を受け取ることができます。各値へのアクセスは$args
の後ろに[]
を付け、[]
の中には数値を書きます。この数値は要素番号と呼ばれており、1番目に受け取った値は$args[0]
、2番目に受け取った値は$args[1]
、n番目に受け取った値は$args[n-1]
でアクセスできます。
よって「sample2.ps1は外部から受け取った値の1つ目($args[0]に代入されている)を Write-Hostコマンドレットでコンソールウィンドウに表示せよ」ということになります。
では、コンソールウィンドウで、
./sample2.ps1 "A"
と入力し[Enter]キーを押してください。実行結果は下記のようになります。
これは、スクリプトファイル「sample2.ps1」実行時に「A」という文字を渡しています。 渡された値は$args変数に代入されているので、結果としてコンソールウィンドウに「A」という文字が表示されます。
スクリプトの実行結果を変数に代入する
最後に、スクリプトファイルの実行結果を変数に代入する方法について説明します。まずは下記コードをテキストエディタで入力して「tashizan.ps1」として保存してください。
return $args[0] + $args[1]
tashizan.ps1では外部から受け取った2つの値を加算してreturnで返します(returnを使用することで値を返すことができます)。
スクリプトファイルの実行結果を変数に代入するには、コンソールウィンドウで、
$result = ./tashizan.ps1 2 3
のようにします。
この場合は、「2」と「3」がtashizan.ps1に渡され、$args[0] + $args[1]
で2つの値を加算し、加算した結果をreturnで返します。返された結果は、$result
変数に代入されます。
コンソールウィンドウで
$result
と入力し[Enter]キーを押してみてください。代入された計算結果の「5」が出力されるはずです。
まとめ
今回は、
- スクリプトファイルの作成方法
- スクリプト実行とセキュリティー
- スクリプトのエラー修正
- スクリプトファイルへの値の渡し方と受け取り方
について説明しました。今回説明したことはほんの入り口にすぎないため、十分理解して次のステップへとつなげてもらえればと思います。
次回は、スクリプトファイルを作成する上で欠かせない変数や演算子、制御構文について説明したいと思います。