PowerShellでPauseを実現するには?Pauseの代用方法も紹介!

PowerShellでPauseを実現するには?Pauseの代用方法も紹介!のアイキャッチイメージ

PowerShellのPauseとは?

PowerShellはWindows10に最初からインストールされているシェル機能です。Windowsには以前からDOS窓と言われるコマンドプロンプトが入っていますが、PowerShellはそれを大幅に機能強化したものと言えるでしょう。

Pauseはコマンドプロンプトで使用できる、Enterキーの入力があるまで処理を一時停止する機能です。スクリプトで処理を行って結果を表示した後、ウィンドウをすぐ閉じないようにするために必要な機能ですが、それをPowerShellで実現する方法を解説します。

PowerShellでもPauseは使える

コマンドプロンプトのPauseをPowerShellで実現するにはどうしたらよいのでしょうか。実は、PowerShellでもPauseを使えます。PowerShellのコマンドラインで、

Pause

と入力してEnterを押すと、

続行するには、Enter キーを押してください…:

と表示され、Enterキーの入力待ちになります。なぜコマンドプロンプトのコマンドがPowerShellで使えるのでしょうか。それはPauseを実行すると、内部で以下を実行してくれるからです。

cmd Pause

Pauseのメッセージを変更するには?

cmdはPowerShellでコマンドプロンプトのコマンドを実行する機能で、それによりPowerShellでPauseを実行してくれるということです。ただし、Enterキーの入力を促すメッセージを変えたい場合は、コマンドプロンプトと同じようにはいきません。

Write-Host Enterキーを押してくださーい!
Pause > NUL

自分で別のメッセージを表示して、Pauseのメッセージをなくしたいのですが、これではエラーになってしまいます。コマンドプロンプトでは「コマンド > NUL」で出力をなくせますが、PowerShellではそれではできません。

Out-Nullで出力を消すことが出来る

PowerShellでは「コマンド | Out-Null」で出力なしにできます。では以下のようにすればうまくいくのでしょうか。

Pause | Out-Null

しかしこれでも表示が出てしまいます。正解は、以下のようにすればメッセージをなくすことができます。/cは指定されたコマンドを実行後、終了するという意味です。

cmd /c Pause | Out-Null

ただし、ここまでの話は「Windows PowerShell」のコマンドラインで入力した場合に限ります。

PowerShellとしてのPauseを自作するべき

cmd Pauseは「Windows PowerShell ISE」で入力したり、ps1ファイルに保存してスクリプトとして実行すると正しく動作しません。ただしPauseのみであればISEでも正しく動作します。結局、PowerShellではPauseはメッセージの内容を変更せずに使うしかないということになります。

そういった経緯から、動作のカスタマイズをしづらいコマンドプロンプトのPauseを使うのではなく、PowerShellの機能でPauseを再現するのが望ましいと言えます。

Read-Hostで代用すれば解決

PowerShellのPauseは以下のようにRead-Hostを使うのがベストでしょう。メッセージを自由に表示できます。メッセージの末尾に「:」が表示されるのも同じです。

Read-Host Enterを押してね!

ただし、Read-Hostは本来、テキストを入力してもらうためのコマンドです。それをPauseの代用にするのは違和感がある人もいるでしょう。

ReadKeyによるPause

やり方の1つとして以下があります。

Write-Host 何かキーを押してください。 -NoNewLine
[Console]::ReadKey() | Out-Null

NoNewLineで改行を防ぎ、任意のキーで先に進みます。Enter以外にも対応できるメリットがあります。ただし、Windows PowerShell ISEではエラーになるという問題があります。

ReadKeyの別のやり方

別のやり方としては以下があります。

Write-Host 何かキーを押してください。
$host.UI.RawUI.ReadKey()

しかしこれも、Windows PowerShell ISEではエラーになります。そこで以下のようにすると、ISEとそれ以外で処理を分けることができます。ただPause処理でこのようなことをするくらいなら、Read-Hostで統一した方が良いでしょう。

if ($psISE) {
Read-Host Enterキーを押してください。
} else {
Write-Host 何かキーを押してください。
$host.UI.RawUI.ReadKey()
}

UIボタンを表示するPause的な処理

グラフィカルなユーザインターフェイスを表示したい場合は、以下のようにします。

Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.MessageBox]::Show(“”Push OK Button.””)

実行すると、ウィンドウ付きのダイアログが表示されます。OKボタンをクリックすると先に進めます。なお、ISEでもそれ以外でも問題なく利用できます。

パスワード入力の方法は?

Pauseと少し違う話になりますが、ただEnterを待つのではなく、パスワードを入力させたい場合は以下のようにします。

$pass = Read-Host “”パスワードを入力してください。”” -AsSecureString

ISEの場合はパスワード用ダイアログが表示され、それ以外では入力すると****のように入力テキストが隠されて表示されます。ところが入力した内容を以下のように表示すると、

Write-Host $pass

以下のように正しく表示されません。-AsSecureStringにより暗号化されて隠蔽されるのです。

System.Security.SecureString

SecureStringの変換

そこで以下のように処理を追加しましょう。

$pass = Read-Host “”パスワードを入力してください。”” -AsSecureString
$bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pass)
$str = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr)
Write-Host $str

こうすると以下のようにパスワードを表示することができます。

パスワードを入力してください。: ****
abcd

パスワードファイルを作成する

PowerShellは[dll名]::API名でWindowsのシステム機能を呼び出すことができます。SecureStringToBSTRでSecureStringをバイナリ文字列に変換し、PtrToStringBSTRでバイナリ文字列を通常の文字列に変換します。

なおパスワードを照合するにあたって、正しいパスワードをスクリプトに記述するわけにはいきません。そこでまず、以下を実行してパスワードファイルを作成します。実行するとダイアログが表示されてパスワードを入力し、passファイルが生成されます。

$cr = Get-Credential
$cr.Password | ConvertFrom-SecureString | Set-Content C:\test\password.pass

パスワードファイルの中身と照合する

後は以下でpassファイルの中身と照合ができます。passファイルの中身も変換が必要な点に注意してください。

$pass = Read-Host “”パスワードを入力してください。”” -AsSecureString
$bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pass)
$str = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr)

$master_pass = Get-Content C:\test\password.pass | ConvertTo-SecureString
$m_bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($master_pass)
$m_str = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($m_bstr)

if ($str -eq $m_str) {
Write-Host パスワードが一致しました。
} else {
Write-Host パスワードが違います。
}

PowerShellのPauseは簡単に実現できる

PowerShellのPauseは簡単に実現が可能だということを解説しましたが、ご理解頂けましたでしょうか。

Read-Hostでも代用できることも解説しました。コマンドプロンプトのPauseも使えますが、なるべくPowerShellのコマンドで実現したほうが良いでしょう。

インフラエンジニア専門の転職サイト「FEnetインフラ」

FEnetインフラはサービス開始から10年以上『エンジニアの生涯価値の向上』をミッションに掲げ、多くのエンジニアの就業を支援してきました。

転職をお考えの方は気軽にご登録・ご相談ください。