「私は常にスクリプトをテストするわけではありませんが、テストを行うときは常に本番環境で行います」
嘘をつかないでください。私たちはみんな一度はやったことがあります。ただし、PowerShellスクリプトを本番環境で実行する際にはリスクを回避する方法があります。組み込みのPowerShell WhatIfパラメーターを使用することを忘れないでください!
環境に変更を加える前に、そのPowerShellコマンドが何をするのかを知ることができたら素晴らしいですよね?コマンドに対して「実行する場合、あなたは何をしますか?」と尋ねることができます。WhatIf
パラメーターを使用できます。
すべてのコンパイル済みPowerShellコマンドレットには、WhatIf
というパラメーターが含まれています。このパラメーターを使用すると、コマンドが予想どおりに動作するか、核融合を引き起こすかを評価することができます。
便利なWhatIf
パラメーターは、組み込みのコマンドレットだけでなく、スクリプトや高度な関数でも利用できます!コードが環境に変更を加える場合、実装することを選択すれば、予期しない結果に対する保護機構が得られます。
前提条件
この記事は、実際に手を動かしながら進めるものです。この旅の間に一緒に進むためには、いくつかの準備が必要です。
- A Windows computer capable of running Powershell v5.1. (Windows 10 and above recommended)
- A script editor like Notepad++, the Windows PowerShell ISE or Visual Studio Code.
この記事では、Windows 10のマシンでVisual Studio Code 1.38(2019年8月)を使用しています。
WhatIf PowerShellパラメーターの定義
要するに、WhatIf
パラメータは、すべての高度な関数やCmdletで利用可能な組み込みのスイッチパラメータです(スクリプトや関数にPowerShellのCmdletBinding
キーワードを追加することで利用できます)。使用すると、コマンドの予想される効果をコンソールに報告しますが、実際にコマンドを実行しません。
すべてのCmdletや高度な関数には、WhatIfパラメータが利用可能です。この記事では、Get-Service
、Stop-Service
、およびNew-Item
のCmdletを使用して、このパラメータをデモンストレーションします。
PowershellのWhatIfサポートのチェック
特定のコマンドがWhatIf
をサポートしているかどうかわからない場合、2つの簡単な方法があります。
Get-Commandの使用
以下のようにSyntax
パラメータを使用して、Get-Command
コマンドを使用してコマンドのメタデータを表示できます。 -WhatIf
の参照が表示されれば、WhatIf
がサポートされています。

Get-Command <CommandName> -Syntax
タブ補完の使用
タブキーを使用して、PowerShellコンソールにチェックしたいコマンドを入力した後、スペース、ダッシュ、’Wh’を入力します。
WhatIf
が表示されれば、そのコマンドにはWhatIf
パラメータがあることがわかります。

PS> <CommandName> -Wh[tab]
CmdletとともにPowerShellのWhatIfパラメータを使用する
WhatIf
パラメーターを活用する方法はさまざまあります。このセクションでは、組み込みのcmdletを使用してWhatIf
パラメーターをすぐに利用する方法を学びます。
ファイルの作成
New-Item
コマンドレットにもWhatIf
パラメーターがあります。この例では、New-Item
コマンドレットを使用して、同じ作業ディレクトリにnewfile1.txtという名前のファイルを作成します。
以下のコマンドを実行すると、newfile.txtという名前のファイルが作成されます。

PS51> New-Item -ItemType File -Path .\newfile1.txt
しかし、もしコマンドが失敗した場合に問題を引き起こす可能性のあるファイルを作成する場合はどうでしょうか?心配ありません。末尾にWhatIf
パラメーターを追加することができます。

New-Item -ItemType File -Path .\newfile1.txt -WhatIf
サービスの停止
Stop-Service
コマンドレットでもWhatIf
パラメーターを使用することができます。この例では、最初の5つのサービスのリストを取得し、Stop-Service
コマンドで停止しています。しかし、実際には停止していません。
代わりに、Stop-Service
コマンドレットが停止するであろうサービスを示す出力メッセージがPowerShellコンソールに表示されます。
PS51> (Get-Service)[0..4] | Stop-Service -WhatIf
PowershellのWhatIfの動作をグローバルに変更する
この時点で、cmdletや高度な関数でWhatIf
パラメーターを使用すると、操作がシミュレートされることを理解しているはずです。コマンドレベルでWhatIf
の動作を影響させています。
WhatIf
の動作は、自動変数$WhatIfPreference
を操作することで、すべてのコマンドに影響を与えるようにも設定することができます。
$WhatIfPreference
変数はブール型です。TrueまたはFalseのいずれかである必要があります。デフォルトでは、Falseに設定されており、コマンドレベルでオーバーライドされない限り、すべてのコマンドのWhatIf
サポートが無効になります。Trueに設定された場合、WhatIfパラメータを明示的に使用するかどうかに関係なく、サポートしているすべてのコマンドが「WhatIf
モード」になります。
$WhatIfPreference
の値をTrue
に変更することで、これをテストすることができます。変更方法は、$WhatIfPreference = $true
です。以下の例では、New-Item
を使用して、WhatIfパラメータを渡さない場合でも、パラメータが渡されたかのように動作します。

PS51> $WhatIfPreference = $true
$WhatIfPreference
をTrue
に変更した場合は、$WhatIfPreference = $false
に戻すことを忘れないでください。
このセクションでは、既存のコマンドレットでのWhatIfサポートの使用方法について学びました。次の手順では、カスタムスクリプトと関数でのWhatIfサポートの構築方法について学びます。
関数でのPowerShell WhatIfサポートの実装
WhatIf
サポートをスクリプトに実装する前に、やり方の間違いと正しい方法を知ることが重要です。次のセクションでそれらを見ていきます。
間違ったやり方:車輪の再発明を避ける
スクリプトの開発者が独自のWhatIf
サポートを実装するために、いくつかのif/thenロジックを使って車輪を再発明することは珍しくありません。以下に例を示します。
開発者は独自のWhatIf
スイッチパラメータを定義しました。そのパラメータの値を使用して、WhatIf
パラメータが使用された場合と使用されなかった場合のロジックを処理するためにif/then構造を使用しています。
上記の関数を以下のようにWhatIfパラメータを使用して実行すると、正常に動作したように見えます。この関数は実際には何も削除せず、コンソールにメッセージを返します。

PS51> Remove-LogFile -name log.txt -WhatIf
問題がないなら、この方法には何が問題なのでしょうか?それは、高度な関数の組み込み機能を無視しているからです。コマンドがオフになった場合にコマンドが行う動作に焦点を当てるだけでなく、この機能を作成するために毎回関数に組み込む必要があります。
代わりに、車輪を再発明せず、SupportsShouldProcess
キーワード を$PSCmdlet.ShouldProcess()
と組み合わせて使用してください。次に進みましょう。
正しく行う方法:SupportsShouldProcessの使用
[CmdletBinding()]
キーワードを使用するすべての関数は「高度な」機能となります。このキーワードにより、WhatIf
のサポートを含むさまざまな機能が追加されます。
すべての高度な関数はWhatIf
の機能をサポートしますが、それを利用するかどうかはあなた次第です。以下のように、最初に[CmdletBinding()]
の括弧の間にSupportsShouldProcess
キーワードを使用する必要があります。
この関数では、WhatIf
パラメータが関数に渡されたかどうかを確認するために、$PSCmdlet
関数変数のShouldProcess()
メソッドを呼び出すことができるようになります。WhatIf
パラメータが使用されると、ShouldProcess()
はFalse
を返します。それ以外の場合、常にTrue
を返します。
WHATIF PARAMETER USED | SHOULDPROCESS() RESULT |
---|---|
True | False |
False | True |
以下に、WhatIf
パラメータを使用してRemove-LogFile
が実行された場合の動作が表示されます。組み込みのcmdletと同じ動作が表示されます。

PS51> Remove-LogFile -name log.txt -WhatIf
概要
この記事では、PowerShellのWhatIfパラメータについて学びました。どのように動作し、どのような利点があるかを理解することができるようになりました。
また、PowerShellの関数に対するフォールセーフが必要な場合、車輪を再発明する必要がないことを知るべきです。代わりに、既存のPowerShellのWhatIf
サポートを活用しましょう!