こんにちは。チェシャ男です。(-皿-)
今回は、
【PowerShellでプロセスの停止を待つ方法】
についてご紹介します。
スクリプト内で、あるプロセスの終了を待ってから次の処理に移行するときなどに Wait-Process コマンドレットを使用することができます。
「多重コピーをかけて完了まで待機する」などの処理を行いたい時に便利なコマンドレットです。
「プロセスの停止まで待つ」のではなく「プロセスを強制的に停止する」場合はこちら↓の記事をご参考ください。
[blogcard url=”https://cheshire-wara.com/powershell/ps-cmdlets/system-service/stop-process/”]
もくじ
Wait-Process でプロセス停止まで待機する
プロセスの停止まで待機するコマンドレットに
Wait-Process
というものがります。
【コマンドレット】
Wait-Process
【オプション】
パターン1(プロセス名で指定)
-Name <プロセス名>
-Timeout <タイムアウト時間>パターン2(プロセスIDで指定)
-Id <プロセスID>
-Timeout <タイムアウト時間>パターン3(オブジェクトで指定)
-Timeout <タイムアウト時間>
-InputObject <プロセスオブジェクト>【入力】
System.Diagnostics.Process
【出力】
None
【エイリアス】
なし
Wait-Processのオプションは比較的少なく使い方も簡単です。
「プロセスとは何か」については「プロセスとは…」をご覧下さい。
プロセス名を指定してプロセス停止を待つ
特定のプロセス名を指定してプロセス停止を待つ方法をご紹介します。
コマンドレット詳細に記載した「パターン1(プロセス名で指定)」のオプションを指定します。
Wait-Process -Name “プロセス名“
プロセス名を確認したい場合は Get-Process コマンドレットを使用します。
[blogcard url=”https://cheshire-wara.com/powershell/ps-cmdlets/system-service/get-process/”]今回は例として「メモ帳」が停止するまで待機してみます。メモ帳のプロセス名は「notepad」ですので “-Name” オプションに notepad を指定します。
まずはメモ帳が起動しているか確認してみましょう。
PS C:\work> Get-Process -Name notepad Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id SI ProcessName ------- ------ ----- ----- ----- ------ -- -- ----------- 143 7 4136 11240 73 0.06 3416 1 notepad
次にプロセス停止まで待機します。
PS C:\work> Wait-Process -Name notepad
と、メモ帳を閉じるまでこのまま実行中が続きます。
上の結果では待機している様子がわかりにくいかもしれませんので実際に試してみてもらった方がわかるかと思います。
プロセス名を指定してプロセス停止まで待機する場合は同じプロセス名を持つ全てのプロセスが停止するまで処理が終わらないことに注意してください。
プロセスIDを指定してプロセス停止を待つ
次に特定のプロセス ID を指定してプロセス停止を待つ方法をご紹介します。
コマンドレット詳細に記載した「パターン2(プロセスIDで指定)」のオプションを指定します。
Wait-Process -ID “プロセスID“
まずは Get-Process コマンドレットを使用してプロセス ID を確認します。
PS C:\work> Get-Process -Name notepad Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id SI ProcessName ------- ------ ----- ----- ----- ------ -- -- ----------- 136 6 3916 11180 72 0.05 3640 1 notepad
プロセスIDは実行中の全てのプロセスに一意に設定されるため「必ず1つのプロセスを指定できる」という特徴があります。
では、「3640」のプロセス ID を指定してメモ帳のプロセスが停止するまで待機してみましょう。
今回は待機中にメモ帳を手動で閉じます。
PS C:\work> #ID指定でプロセス停止まで待機する PS C:\work> Wait-Process -Id 3640 PS C:\work> PS C:\work> #★手動でメモ帳を閉じました★ PS C:\work> PS C:\work> #停止した「3640」のプロセスを確認 PS C:\work> Get-Process -Id 3640 Get-Process : プロセス識別子 3640 のプロセスが見つかりません。 発生場所 行:1 文字:1 + Get-Process -Id 3728 + ~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (3640:Int32) [Get-Process], ProcessCommandException + FullyQualifiedErrorId : NoProcessFoundForGivenId,Microsoft.PowerShell.Commands.GetProcessCommand
このように指定したプロセスIDが停止すれば次の処理に進むことができます。
InputObject オプションでプロセス停止を待つ
3つ目の方法として “-InputObject” オプションを使用してプロセスの停止を待つ方法があります。
InputObject として指定するオブジェクトは「System.Diagnostics.Process」型である必要があります。
簡単に表すとプロセス専用型のオブジェクトです。
Wait-Process -InputObject “プロセスオブジェクト“
Wait-Process コマンドレットの “InputObject” オプションでオブジェクトを指定する場合に良く使う手法は
立ち上げたプロセスの情報を変数に格納して待機する
だと思います。
「Start-Process」で “-PassThru” オプションを指定すると立ち上げたプロセスの情報をオブジェクトとして保持することができます。
[blogcard url=”https://cheshire-wara.com/powershell/ps-cmdlets/system-service/start-process/”]下の例では、
プロセス起動 ⇒ オブジェクト化 ⇒ 終了待機
という流れで実行しています。
PS C:\work> #メモ帳を起動して変数に格納する PS C:\work> $Obj = Start-Process -FilePath notepad -PassThru PS C:\work> PS C:\work> #オブジェクトの中身を確認 PS C:\work> $Obj Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id SI ProcessName ------- ------ ----- ----- ----- ------ -- -- ----------- 143 7 4272 11404 73 0.06 5392 1 notepad PS C:\work> #オブジェクトの型を確認 PS C:\work> $Obj.GetType().FullName System.Diagnostics.Process PS C:\work> PS C:\work> #メモ帳の終了を待機(オブジェクト指定)⇒手動で停止 PS C:\work> Wait-Process -InputObject $Obj PS C:\work> PS C:\work> #プロセスが無いことを確認 PS C:\work> Get-Process -InputObject $Obj Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id SI ProcessName ------- ------ ----- ----- ----- ------ -- -- ----------- 0 0 0 0 0.08 5392
GetType メソッドによる型の確認でも「System.Diagnostics.Process」であることがわかりますね。
起動したメモ帳のプロセス情報を変数$Objを使って、「Start-Process」「Wait-Process」「Get-Process」コマンドレット間のやり取りを行っています。
この “InputObject” による手法は
「スクリプト中に別のアプリケーションやファイルを並列実行し処理が完了したら次に進む」
なんてことをやりたい時には非常に活躍します。
プロセス停止の待機にタイムアウトを設定する
3つのパターンを紹介してきましたが全てのパターンに共通して “-Timeout” オプションが用意されています。
Wait-Process コマンドレットはピュアなので何も指定しなければ、ずっと待ち続けてしまいます。
もし、自動化するためのスクリプトで待機され続けてしまうと困りますよね。
そこで最大何秒待機するかを設定するために “-Timeout” オプションを使用します。
Wait-Process <対象> -Timeout <待機時間(秒)>
タイムアウトの指定は秒単位(S)で指定します。
PS C:\work> #停止待機のプロセスを確認 PS C:\work> Get-Process -Name notepad Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id SI ProcessName ------- ------ ----- ----- ----- ------ -- -- ----------- 137 6 3984 11224 72 0.06 844 1 notepad PS C:\work> PS C:\work> #10秒待って停止しなければタイムアウトエラー PS C:\work> Wait-Process -Id 844 -Timeout 10 Wait-Process : This command stopped operation because process "notepad (844)" is not stopped in the specified time-out. At line:1 char:1 + Wait-Process -Id 844 -Timeout 10 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : CloseError: (System.Diagnostics.Process (notepad):Process) [Wait-Process], TimeoutException + FullyQualifiedErrorId : ProcessNotTerminated,Microsoft.PowerShell.Commands.WaitProcessCommand
このようにプロセス停止の待機時間に制限を設けることができます。
使い方によっては非常に便利になりそうですね。
まとめ
あるプロセスが停止するまで待機する場合は
Stop-Process <待機する対象>
を使用する。
待機するプロセスの指定方法は、
[プロセス名で指定] Get-Process -Name <プロセス名> [プロセスIDで指定] Get-Process -Id <プロセスID> [オブジェクトで指定] Get-Process -InputPbject <プロセスオブジェクト>待機時間を制限する場合は、
-Timeout <待ち時間(秒)>