はじめに
今回は、他のPowerShellのScriptを実行するPowerShell Scriptを作成します。
PowerShellでいくつか簡単なツールを作ります。
ツールAを実行して、ツールBを実行するみたいに、複数のツールをシーケンシャルに実行したくなります。
ということで、調べてみるとできそうということなので、サンプルを備忘としてまとめます。
今回実施する内容
今回は、参照元のScriptと参照先のScript(RefferredScript.ps1)を作成し、参照元から参照先のScriptを参照します。
実行方法を2つ見つけたのでその2つで実施します。
なお、2つのScriptは同階層に存在するものとします。
・.(ドット)を使用して実現
・Invoke-Expressionを使用して実現
ソースコード(Git Hub)
環境
OS: Windows 10 JP (64bit)
PowerShell version: 5.1.19041.1
参考
なし
用語
.(ドット)を使用して実現
シンプルな関数の読み込み
Script | 説明 |
---|---|
BaseScript.ps1 | 参照元Script。参照先Scriptの関数を呼び出す。 |
ReferredScript.ps1 | 参照先Script。ターミナルに文字列を出力する関数だけ定義。 |
参照元Scriptから参照先Scriptの関数を呼び出して実行します。
単に文字列をターミナルに出力するだけです。
ソースコード
try {
. .\referredScript.ps1
ShowMessage("参照元Scriptで、参照先Scriptの関数を参照して実行します。")
} catch {
Write-Host $Error[0]
}
function ShowMessage {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]$Message
)
Write-Host $Message
}
<実行結果>
参照元Scriptの関数を参照して実行します。
ソースコードの説明
2つのScriptは同じ階層に置きます。
参照先Scriptは単にWrite-Hostで$Messageをターミナルに表示するだけのシンプルな関数です。
参照元Scriptでは、
. .\referredScript.ps1
で、referredScript.ps1を実行します。といっても実行文はなく関数記載だけのため、関数の読み込みだけ実施されます。
その後ShowMessage
で、参照元Scriptから参照先Scriptの関数を実行します。
.(ドット)の説明
これでいけるということですね。最初の**「.」**がなじみがなかったので調べてみると、
PowerShell用語集
|期間|定義|
|:--|:--|
ドット ソース| PowerShell では、コマンドの前にドットとスペースを入力することによってコマンドを開始すること。 ドット ソースのコマンドは、新しいスコープではなく、現在のスコープで実行されます。 コマンドが作成するすべての変数、エイリアス、関数、またはドライブは、現在のスコープで作成され、コマンドが完了すると使用できるようになります。|
なるほど。これでコマンド開始することになるんですね。そしてスコープは現在のスコープと。
「期間」は単なる翻訳のミスですね。ただしくは「Term」なので「用語」ですね。
参照先Scriptで実行文がある場合の動作
実際に使用するとなると、最初に試したようなライブラリ的な使い方もすると思いますが、別のツール(別のScript)を実行するという使い方もすると思います。
ということで、参照先Scriptに実行文を入れた場合の動作を試します。
Script | 説明 |
---|---|
BaseScript2.ps1 | 参照元Script。参照先Scriptの関数を呼び出す。 |
ReferredScript2.ps1 | 参照先Script。ターミナルに文字列を出力する関数を定義。加えてその関数を実行 |
ソースコード
try {
. .\referredScript2.ps1
ShowMessage("参照元Scriptで、参照先Scriptの関数を参照して実行します。")
} catch {
Write-Host $Error[0]
}
function ShowMessage {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]$Message
)
Write-Host $Message
}
ShowMessage("参照先Scriptです。ShowMessageを実行します。")
<実行結果>
参照先Scriptです。ShowMessageを実行します。
参照元Scriptの関数を参照して実行します。
ソースコードの説明
これを実行すると参照先Scriptの実行文が実行された後、参照元Scriptの読み込んだShowMessageが実行されるということです。
結局両方実行されるってことですね。
これなら、単体で参照先Scriptを使ってもよいし、参照元Scriptから読み込んで使ってもよいし、期待通りです。
Invoke-Expressionを使用して実現
シンプルな関数の読み込み
Script | 説明 |
---|---|
BaseScript3.ps1 | 参照元Script。参照先Scriptの関数を呼び出す。 |
ReferredScript3.ps1 | 参照先Script。ターミナルに文字列を出力する関数だけ定義。 |
参照元Scriptから参照先Scriptの関数を呼び出して実行します。
単に文字列をターミナルに出力するだけです。
ソースコード
try {
Invoke-Expression .\referredScript3.ps1
ShowMessage("参照元Scriptで、参照先Scriptの関数を参照して実行します。")
} catch {
Write-Host $Error[0]
}
function ShowMessage {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]$Message
)
Write-Host $Message
}
<実行結果>
参照元Scriptの関数を参照して実行します。
Invoke-Expressionの説明
「.(ドット)を使用して実現」と結果は同じです。
動作は似たようなものかなと思いますが、PowershelのドキュメントInvoke-Expressionから引用すると、以下です。
###Example 2: Run a script on the local computer
Invoke-Expression -Command "C:\ps-test\testscript.ps1" "C:\ps-test\testscript.ps1" | Invoke-Expression
These commands use
Invoke-Expression
to run a script, TestScript.ps1, on the local computer. The two commands are equivalent. The first uses the Command parameter to specify the command to run. The second uses a pipeline operator (|
) to send the command string toInvoke-Expression
.
コマンドを開始するといっているのでやはり同じようです。パイプラインも使えるようです。
参照先Scriptで実行文がある場合の動作
「.(ドット)を使用して実現」と同様に、参照先Scriptに実行文を入れた場合の動作を試します。
Script | 説明 |
---|---|
BaseScript4.ps1 | 参照元Script。参照先Scriptの関数を呼び出す。 |
ReferredScript4.ps1 | 参照先Script。ターミナルに文字列を出力する関数を定義。加えてその関数を実行 |
ソースコード
try {
Invoke-Expression .\referredScript4.ps1
ShowMessage("参照元Scriptで、参照先Scriptの関数を参照して実行します。")
} catch {
Write-Host $Error[0]
}
function ShowMessage {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]$Message
)
Write-Host $Message
}
ShowMessage("参照先Scriptです。ShowMessageを実行します。")
<実行結果>
参照先Scriptです。ShowMessageを実行します。
参照元Scriptの関数を参照して実行します。
ソースコードの説明
これを実行すると参照先Scriptの実行文が実行された後、参照元Scriptの読み込んだShowMessageが実行されるということです。
結局両方実行されるってことですね。
結果は「.(ドット)を使用して実現」と同じですね。
参照先Scriptで実行文があって結果を参照元Scriptに戻す動作
参照元Scriptで参照先Scriptを呼び出す場合、その処理が正常に終わったかどうか参照したくなります。
例えば、ツールAを実行して正常に終了したならば、ツールBを実行というように、正常かどうかを示す戻り値を返したくなります。
ということで試してみます。
Script | 説明 |
---|---|
BaseScript5.ps1 | 参照元Script。参照先Scriptの関数を呼び出す。 |
ReferredScript5.ps1 | 参照先Script。ターミナルに文字列を出力する関数を定義。加えてその関数を実行 |
ソースコード
try {
$result = Invoke-Expression .\ReferredScript5.ps1
if ($result -eq 1) {
ShowMessage("参照元Scriptの関数の戻り値を取得成功。")
} else {
ShowMessage("参照元Scriptの関数の戻り値を取得失敗。")
}
} catch {
Write-Host $Error[0]
}
function ShowMessage {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]$Message
)
Write-Host $Message
1
}
ShowMessage("参照先Scriptです。ShowMessageを実行します。")
<実行結果>
参照先Scriptです。ShowMessageを実行します。
参照元Scriptの関数の戻り値を取得成功。
ソースコードの説明
PowerShell:BaseScript5.ps1では、ReferredScript5.ps1の実行文の戻り値を$result
に代入して、その値が1か判断し、ターミナルに出力します。
ReferredScript5.ps1では、ShowMessage関数内で、1を出力します。
ということで、戻り値1を$resultに代入ができて、それに応じた動作を実行できました。
期待通りです。
おわりに
今回は、他のPowerShellのScriptを実行するPowerShell Scriptを作成し、動作を確認しました。
期待通りの動作ができて満足です。
Invoke-Expressionのほうが、明示的でわかりやすいかなと思いました。
.(ドット)だと、戻り値がどうやって帰ってくるのかわからなかったですし。
これをベースにツールを複数実行するScriptを試してみることにします。
何かあればまた記事更新します。