PowerShellの $PSCmdlet を徹底解説!実践で使える基本と応用

PowerShellは、Windowsや他のプラットフォームで使える強力なコマンドラインツールです。

その中でも、$PSCmdlet は、特に高度なスクリプトやカスタムコマンドレットを作成する際に欠かせない変数です。

本記事では、$PSCmdlet の基本的な使い方から応用例までを徹底解説し、演習問題を通じて実際に活用できるスキルを身につけます。


スポンサーリンク

$PSCmdlet とは?

$PSCmdlet は、PowerShellスクリプトや関数内で使える特別な自動変数で、現在のコマンドレットやスクリプトの実行状況に関する情報を取得するために使用されます。

この変数を使うことで、コマンドレットの実行コンテキストにアクセスしたり、特定のメソッドやプロパティを利用してスクリプトの動作を柔軟に制御することができます。


$PSCmdlet の主なプロパティとメソッド

$PSCmdlet.MyInvocation

$PSCmdlet.MyInvocation は、実行中のコマンドレットやスクリプトに関する情報を提供します。

これには、呼び出し元のスクリプト名やコマンドレットのパラメータなどが含まれます。

function Test-MyInvocation {
    $PSCmdlet.MyInvocation | Format-List *
}
Test-MyInvocation

上記の例を実行すると、関数 Test-MyInvocation がどのように呼び出されたかに関する詳細な情報が表示されます。

$PSCmdlet.WriteObject()

$PSCmdlet.WriteObject() メソッドは、出力をPowerShellパイプラインに渡すために使います。

標準の Write-Output コマンドレットと同様の働きをします。

function Test-WriteObject {
    $PSCmdlet.WriteObject("Hello, PowerShell!")
}
Test-WriteObject

この関数を実行すると、”Hello, PowerShell!” という文字列が出力されます。

$PSCmdlet.ShouldProcess()

ShouldProcess() メソッドは、操作を実行する前にユーザーの確認を求めるために使用されます。

これは、特にファイルや設定を変更するコマンドレットで便利です。

function Test-ShouldProcess {
    if ($PSCmdlet.ShouldProcess("target", "action")) {
        $PSCmdlet.WriteObject("Action executed!")
    }
}
Test-ShouldProcess

実行時に確認を求め、ユーザーが承認すればアクションが実行されます。

$PSCmdlet.ThrowTerminatingError()

ThrowTerminatingError() メソッドは、スクリプトの実行を停止し、エラーを発生させるために使用されます。

これは、重大なエラーが発生した場合にスクリプトを即座に中断させるために便利です。

function Test-Error {
    $errorRecord = New-Object System.Management.Automation.ErrorRecord `
        ([Exception] "重大なエラー"), "ErrorID", [System.Management.Automation.ErrorCategory]::InvalidOperation, $null
    $PSCmdlet.ThrowTerminatingError($errorRecord)
}
Test-Error

この関数を実行すると、指定されたエラーが発生し、スクリプトの実行が停止します。

$PSCmdlet.WriteError()

WriteError() メソッドは、非終了エラーを発生させるために使用されます。

スクリプトの実行を完全に停止せず、エラーを報告したい場合に使います。

function Test-WriteError {
    $errorRecord = New-Object System.Management.Automation.ErrorRecord `
        ([Exception] "非終了エラー"), "NonTerminatingError", [System.Management.Automation.ErrorCategory]::OperationStopped, $null
    $PSCmdlet.WriteError($errorRecord)
}
Test-WriteError

この関数を実行すると、エラーメッセージが表示されますが、スクリプトは停止せずに実行を続行します。

$PSCmdlet.WriteWarning()

WriteWarning() メソッドは、警告メッセージを表示するために使用されます。

警告メッセージは、ユーザーに注意を促すために役立ちますが、スクリプトの実行は継続されます。

function Test-WriteWarning {
    $PSCmdlet.WriteWarning("これは警告メッセージです。")
}
Test-WriteWarning

この関数を実行すると、警告メッセージが表示されます。

$PSCmdlet.WriteVerbose()

WriteVerbose() メソッドは、詳細メッセージを表示するために使用されます。

スクリプトがどのように進行しているかを詳細に知りたい場合に役立ちます。

function Test-WriteVerbose {
    $PSCmdlet.WriteVerbose("詳細なデバッグメッセージ")
}
Test-WriteVerbose -Verbose

この関数を実行する際に -Verbose オプションを指定すると、詳細なメッセージが表示されます。


$PSCmdlet を活用した実践例

コマンドレットの安全な実行

ShouldProcess() メソッドを使用して、ファイル削除のような破壊的な操作を確認する例です。

function Remove-FileSafe {
    param(
        [string]$FilePath
    )

    if (-not (Test-Path $FilePath)) {
        Write-Host "ファイルが見つかりません: $FilePath"
        return
    }

    if ($PSCmdlet.ShouldProcess($FilePath, "削除")) {
        Remove-Item $FilePath
        Write-Host "$FilePath を削除しました。"
    } else {
        Write-Host "$FilePath の削除をキャンセルしました。"
    }
}
Remove-FileSafe -FilePath "C:\testfile.txt"

エラーログと警告の活用

次に、WriteError()WriteWarning() を使って、ユーザーに適切なメッセージを出力する例です。

function Check-FileAndDelete {
    param(
        [string]$FilePath
    )

    if (-not (Test-Path $FilePath)) {
        $errorRecord = New-Object System.Management.Automation.ErrorRecord `
            ([Exception] "ファイルが見つかりません"), "FileNotFound", [System.Management.Automation.ErrorCategory]::ObjectNotFound, $FilePath
        $PSCmdlet.WriteError($errorRecord)
        return
    }

    $PSCmdlet.WriteWarning("ファイル削除の確認が必要です。")

    if ($PSCmdlet.ShouldProcess($FilePath, "削除")) {
        Remove-Item $FilePath
        Write-Host "$FilePath を削除しました。"
    } else {
        Write-Host "$FilePath の削除をキャンセルしました。"
    }
}
Check-FileAndDelete -FilePath "C:\nonexistentfile.txt"

詳細ログの表示

WriteVerbose() を使って、詳細な進行状況をユーザーに見せる例です。

function Copy-FileWithVerbose {
    param(
        [string]$SourcePath,
        [string]$DestinationPath
    )

    $PSCmdlet.WriteVerbose("コピー元: $SourcePath")
    $PSCmdlet.WriteVerbose("コピー先: $DestinationPath")

    if (Test-Path $SourcePath) {
        Copy-Item $SourcePath -Destination $DestinationPath
        Write-Host "ファイルがコピーされました。"
    } else {
        $PSCmdlet.WriteError((New-Object System.Management.Automation.ErrorRecord `
            ([Exception] "コピー元ファイルが見つかりません"), "SourceNotFound", [System.Management.Automation.ErrorCategory]::ObjectNotFound, $SourcePath))
    }
}
Copy-FileWithVerbose -SourcePath "C:\file.txt" -DestinationPath "C:\backup\file.txt" -Verbose

演習問題

演習1: ShouldProcess を使ったファイルコピー関数の作成

次の要件を満たすPowerShell関数を作成してください。

  • 関数名は Copy-FileSafe 。
  • パラメータは2つ:コピー元のパス (SourcePath) とコピー先のパス (DestinationPath)。
  • ファイルをコピーする前に ShouldProcess() を使って、ユーザーに確認を求める。
  • コピー先に既にファイルが存在する場合は、上書き確認を行う。
解答例
function Copy-FileSafe {
    param(
        [string]$SourcePath,
        [string]$DestinationPath
    )

    if (-not (Test-Path $SourcePath)) {
        Write-Host "コピー元ファイルが見つかりません: $SourcePath"
        return
    }

    if (Test-Path $DestinationPath) {
        if ($PSCmdlet.ShouldProcess($DestinationPath, "上書きコピー")) {
            Copy-Item $SourcePath -Destination $DestinationPath -Force
            Write-Host "$DestinationPath にファイルを上書きしました。"
        } else {
            Write-Host "コピーをキャンセルしました。"
        }
    } else {
        if ($PSCmdlet.ShouldProcess($DestinationPath, "コピー")) {
            Copy-Item $SourcePath -Destination $DestinationPath
            Write-Host "$DestinationPath にファイルをコピーしました。"
        } else {
            Write-Host "コピーをキャンセルしました。"
        }
    }
}

演習2: WriteError と WriteWarning を使ったファイル削除関数の作成

次の要件を満たすPowerShell関数を作成してください。

  • 関数名は Delete-FileSafe 。
  • パラメータは1つ:ファイルパス (FilePath)。
  • ファイルが存在しない場合は、WriteError() を使ってエラーメッセージを表示する。
  • ファイル削除前に WriteWarning() で警告メッセージを表示し、削除を確認する。
解答例
function Delete-FileSafe {
    param(
        [string]$FilePath
    )

    if (-not (Test-Path $FilePath)) {
        $errorRecord = New-Object System.Management.Automation.ErrorRecord `
            ([Exception] "ファイルが見つかりません: $FilePath"), "FileNotFound", [System.Management.Automation.ErrorCategory]::ObjectNotFound, $FilePath
        $PSCmdlet.WriteError($errorRecord)
        return
    }

    $PSCmdlet.WriteWarning("ファイル削除の確認が必要です。")

    if ($PSCmdlet.ShouldProcess($FilePath, "削除")) {
        Remove-Item $FilePath
        Write-Host "$FilePath を削除しました。"
    } else {
        Write-Host "$FilePath の削除をキャンセルしました。"
    }
}

まとめ

本記事では、PowerShellの $PSCmdlet 変数を使って、コマンドレットの実行状況を管理したり、エラー処理や警告、詳細メッセージを出力する方法を解説しました。

特に、ShouldProcess、WriteError、WriteWarning、および WriteVerbose といったメソッドを使うことで、スクリプトをより安全かつ柔軟に実行することができます。