👻

[PowerShell]定数が定義済みかチェックするFunction

2024/07/09に公開

概要

すでに定義されている環境で定数を定義しようとすると、Set-Variable : 変数 "定数名" は読み取り専用または定数であるため、上書きできません。というエラーが発生します。

このエラーはPowerShellスクリプトで定数を使用し、そのスクリプトを検証するシチュエーションなどで発生し、
エラーノイズとなってしまいます。

不要なエラーを抑止するため、今回は定数が定義済みかチェックするFunctionを作成しました。

定義済みの状態で定義するとエラー

実際のエラーは下記のとおり。

エラー「Set-Variable
# 定数がすでに定義済み
PS C:\Users\"ユーザー名"> $STRING1
文字列1
PS C:\Users\"ユーザー名">
# すでに定義された状態で同じ定数を定義しようとするとエラー発生
PS C:\Users\"ユーザー名"> Set-Variable -Name 'STRING1' -Value '文字列1' -Option Constant
Set-Variable : 変数 STRING1 は読み取り専用または定数であるため、上書きできません。
発生場所 行:1 文字:1
+ Set-Variable -Name 'STRING1' -Value '文字列1' -Option Constant
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : WriteError: (STRING1:String) [Set-Variable], SessionStateUnauthorizedAccessException
    + FullyQualifiedErrorId : VariableNotWritable,Microsoft.PowerShell.Commands.SetVariableCommand

PS C:\Users\"ユーザー名">

対応方法

定数が定義済みかチェックするコード

下記が自作したFunciton。

定数が定義済みかチェックするFunction
function Test-ConstantDefined {
    param (
        [System.String[]]$Constants
    )
    foreach ($const in $Constants) {
        [System.String]$constValue = (Get-Variable -Name $const -ErrorAction SilentlyContinue)
        # Nullの場合は未定義として判断
        # (空文字や空白のみは定数として定義される可能性があるためチェックしない)
        if ($null -eq $constValue) {
            return $false
        }
    }
    return $true
}

自作Functionを検証

検証するための下記コードで期待通り動作するか確認してみます。

自作Functionを検証するコード
# 定数名の配列
$constantsArray = @('STRING1', 'STRING2', 'NUMBER1', 'NUMBER2')

# 配列内のすべての定数が$nullの場合、定数として設定
if (-not (Test-ConstantDefined -Constants $constantsArray)) {
    Set-Variable -Name $constantsArray[0] -Value '文字列1' -Option Constant
    Set-Variable -Name $constantsArray[1] -Value '文字列2' -Option Constant
    Set-Variable -Name $constantsArray[2] -Value 1 -Option Constant
    Set-Variable -Name $constantsArray[3] -Value 2 -Option Constant

    Write-Output '定数をセットしました。'
}
else {
    Write-Warning 'すでに定数が設定されていた為、定数の宣言をスキップ。'
}

定数が定義されていない場合は、以下のとおり「定数をセットしました。」というメッセージが出力され、
期待通り定数が定義できたことを確認。

定数が未定義の場合
PS C:\Users\"ユーザー名"> # 定数名の配列
>> $constantsArray = @('STRING1', 'STRING2', 'NUMBER1', 'NUMBER2')
>>
>> # 配列内のすべての定数が$nullの場合、定数として設定
>> if (-not (Test-ConstantDefined -Constants $constantsArray)) {
>>     Set-Variable -Name $constantsArray[0] -Value '文字列1' -Option Constant
>>     Set-Variable -Name $constantsArray[1] -Value '文字列2' -Option Constant
>>     Set-Variable -Name $constantsArray[2] -Value 1 -Option Constant
>>     Set-Variable -Name $constantsArray[3] -Value 2 -Option Constant
>>
>>     Write-Output '定数をセットしました。'
>> }
>> else {
>>     Write-Warning 'すでに定数が設定されていた為、定数の宣言をスキップ。'
>> }
定数をセットしました。
PS C:\Users\"ユーザー名">

一方、定数が定義済みの状態で、もう一度おなじコードで変数を定義しようとすると、
以下のとおり「警告: すでに定数が設定されていた為、定数の宣言をスキップ。」と警告メッセージが表示され、
期待通り定数の定義する処理がスキップできたことを確認。

定数が定義済みの場合
PS C:\Users\"ユーザー名"> # 定数名の配列
>> $constantsArray = @('STRING1', 'STRING2', 'NUMBER1', 'NUMBER2')
>>
>> # 配列内のすべての定数が$nullの場合、定数として設定
>> if (-not (Test-ConstantDefined -Constants $constantsArray)) {
>>     Set-Variable -Name $constantsArray[0] -Value '文字列1' -Option Constant
>>     Set-Variable -Name $constantsArray[1] -Value '文字列2' -Option Constant
>>     Set-Variable -Name $constantsArray[2] -Value 1 -Option Constant
>>     Set-Variable -Name $constantsArray[3] -Value 2 -Option Constant
>>
>>     Write-Output '定数をセットしました。'
>> }
>> else {
>>     Write-Warning 'すでに定数が設定されていた為、定数の宣言をスキップ。'
>> }
警告: すでに定数が設定されていた為、定数の宣言をスキップ。
PS C:\Users\"ユーザー名">

まとめ

  • 定数を定義済みかチェックできるFunctionを自作した
  • PowerShellスクリプトで定数を取り扱い検証時のエラーノイズを減らしたい場合に活用

関連記事

https://haretokidoki-blog.com/pasocon_powershell-startup/
https://zenn.dev/haretokidoki/articles/7e6924ff0cc960
https://zenn.dev/haretokidoki/articles/fb6830f9155de5

GitHubで編集を提案

Discussion