awesome-copilot/instructions/powershell.instructions_ja.md

11 KiB
Raw Blame History

applyTo description
**/*.ps1,**/*.psm1 Microsoftガイドラインに基づくPowerShellコマンドレットとスクリプトのベストプラクティス

PowerShellコマンドレット開発ガイドライン

このガイドは、GitHub Copilotが慣用的で安全で保守可能なスクリプトを生成するのに役立つPowerShell固有の指示を提供します。MicrosoftのPowerShellコマンドレット開発ガイドラインと整合性を保っています。

命名規則

  • 動詞-名詞形式:

    • 承認されたPowerShell動詞を使用するGet-Verb
    • 単数形の名詞を使用する
    • 動詞と名詞の両方にPascalCaseを使用する
    • 特殊文字とスペースを避ける
  • パラメーター名:

    • PascalCaseを使用する
    • 明確で説明的な名前を選択する
    • 常に複数でない限り単数形を使用する
    • PowerShell標準名に従う
  • 変数名:

    • パブリック変数にはPascalCaseを使用する
    • プライベート変数にはcamelCaseを使用する
    • 省略形を避ける
    • 意味のある名前を使用する
  • エイリアスの回避:

    • 完全なコマンドレット名を使用する
    • スクリプトでエイリアスを使用しないgciの代わりにGet-ChildItemを使用
    • カスタムエイリアスを文書化する
    • 完全なパラメーター名を使用する

function Get-UserProfile {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$Username,

        [Parameter()]
        [ValidateSet('Basic', 'Detailed')]
        [string]$ProfileType = 'Basic'
    )

    process {
        # ロジックをここに記述
    }
}

パラメーター設計

  • 標準パラメーター:

    • 共通パラメーター名を使用する(PathNameForce
    • 組み込みコマンドレット規約に従う
    • 専門用語にはエイリアスを使用する
    • パラメーターの目的を文書化する
  • パラメーター名:

    • 常に複数でない限り単数形を使用する
    • 明確で説明的な名前を選択する
    • PowerShell規約に従う
    • PascalCase形式を使用する
  • 型選択:

    • 一般的な.NET型を使用する
    • 適切な検証を実装する
    • 限定されたオプションにはValidateSetを検討する
    • 可能な場合はタブ補完を有効にする
  • スイッチパラメーター:

    • ブール型フラグには[switch]を使用する
    • $true/$falseパラメーターを避ける
    • 省略時はデフォルトで$falseとする
    • 明確なアクション名を使用する

function Set-ResourceConfiguration {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$Name,
        
        [Parameter()]
        [ValidateSet('Dev', 'Test', 'Prod')]
        [string]$Environment = 'Dev',
        
        [Parameter()]
        [switch]$Force,
        
        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string[]]$Tags
    )
    
    process {
        # ロジックをここに記述
    }
}

パイプラインと出力

  • パイプライン入力:

    • 直接オブジェクト入力にはValueFromPipelineを使用する
    • プロパティマッピングにはValueFromPipelineByPropertyNameを使用する
    • パイプライン処理にはBegin/Process/Endブロックを実装する
    • パイプライン入力要件を文書化する
  • 出力オブジェクト:

    • フォーマットされたテキストではなくリッチオブジェクトを返す
    • 構造化データにはPSCustomObjectを使用する
    • データ出力にWrite-Hostを避ける
    • 下流コマンドレット処理を有効にする
  • パイプラインストリーミング:

    • 一度に一つのオブジェクトを出力する
    • ストリーミングにはprocessブロックを使用する
    • 大きな配列の収集を避ける
    • 即座の処理を有効にする
  • PassThruパターン:

    • アクションコマンドレットではデフォルトで出力なしとする
    • オブジェクトリターンには-PassThruスイッチを実装する
    • -PassThruで変更/作成されたオブジェクトを返す
    • ステータス更新にはverbose/warningを使用する

function Update-ResourceStatus {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [string]$Name,

        [Parameter(Mandatory)]
        [ValidateSet('Active', 'Inactive', 'Maintenance')]
        [string]$Status,

        [Parameter()]
        [switch]$PassThru
    )

    begin {
        Write-Verbose "リソースステータス更新プロセスを開始します"
        $timestamp = Get-Date
    }

    process {
        # 各リソースを個別に処理
        Write-Verbose "リソースを処理中: $Name"
        
        $resource = [PSCustomObject]@{
            Name = $Name
            Status = $Status
            LastUpdated = $timestamp
            UpdatedBy = $env:USERNAME
        }

        # PassThruが指定された場合のみ出力
        if ($PassThru) {
            Write-Output $resource
        }
    }

    end {
        Write-Verbose "リソースステータス更新プロセスが完了しました"
    }
}

エラーハンドリングと安全性

  • ShouldProcess実装:

    • [CmdletBinding(SupportsShouldProcess = $true)]を使用する
    • 適切なConfirmImpactレベルを設定する
    • システム変更には$PSCmdlet.ShouldProcess()を呼び出す
    • 追加確認にはShouldContinue()を使用する
  • メッセージストリーム:

    • -Verboseでの操作詳細にはWrite-Verbose
    • 警告条件にはWrite-Warning
    • 非終了エラーにはWrite-Error
    • 終了エラーにはthrow
    • ユーザーインターフェーステキスト以外ではWrite-Hostを避ける
  • エラーハンドリングパターン:

    • エラー管理にはtry/catchブロックを使用する
    • 適切なErrorAction設定を設定する
    • 意味のあるエラーメッセージを返す
    • 必要に応じてErrorVariableを使用する
    • 適切な終了vs非終了エラーハンドリングを含める
  • 非対話型設計:

    • パラメーター経由で入力を受け入れる
    • スクリプトでRead-Hostを避ける
    • 自動化シナリオをサポートする
    • すべての必要な入力を文書化する

function Remove-UserAccount {
    [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')]
    param(
        [Parameter(Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [string]$Username,

        [Parameter()]
        [switch]$Force
    )

    begin {
        Write-Verbose "ユーザーアカウント削除プロセスを開始します"
        $ErrorActionPreference = 'Stop'
    }

    process {
        try {
            # 検証
            if (-not (Test-UserExists -Username $Username)) {
                Write-Error "ユーザーアカウント '$Username' が見つかりません"
                return
            }

            # 確認
            $shouldProcessMessage = "ユーザーアカウント '$Username' を削除"
            if ($Force -or $PSCmdlet.ShouldProcess($Username, $shouldProcessMessage)) {
                Write-Verbose "ユーザーアカウントを削除中: $Username"
                
                # メイン操作
                Remove-ADUser -Identity $Username -ErrorAction Stop
                Write-Warning "ユーザーアカウント '$Username' が削除されました"
            }
        }
        catch [Microsoft.ActiveDirectory.Management.ADException] {
            Write-Error "Active Directoryエラー: $_"
            throw
        }
        catch {
            Write-Error "ユーザーアカウント削除の予期しないエラー: $_"
            throw
        }
    }

    end {
        Write-Verbose "ユーザーアカウント削除プロセスが完了しました"
    }
}

ドキュメントとスタイル

  • コメントベースヘルプ: パブリック向けの関数またはコマンドレットにはコメントベースヘルプを含める。関数内に<# ... #>ヘルプコメントを追加し、少なくとも以下を含める:

    • .SYNOPSIS 簡潔な説明
    • .DESCRIPTION 詳細な説明
    • .EXAMPLE 実用的な使用法のセクション
    • .PARAMETER 説明
    • .OUTPUTS 返される出力の型
    • .NOTES 追加情報
  • 一貫したフォーマット:

    • 一貫したPowerShellスタイルに従う
    • 適切なインデント4スペース推奨を使用する
    • 文と同じ行に開始中括弧を配置
    • 新しい行に終了中括弧を配置
    • パイプライン演算子の後に改行を使用
    • 関数とパラメーター名にPascalCaseを使用
    • 不要な空白を避ける
  • パイプラインサポート:

    • パイプライン関数にはBegin/Process/Endブロックを実装する
    • 適切な場合はValueFromPipelineを使用する
    • プロパティ名によるパイプライン入力をサポートする
    • フォーマットされたテキストではなく適切なオブジェクトを返す
  • エイリアスを避ける: 完全なコマンドレット名とパラメーターを使用する

    • スクリプトでエイリアスを使用しないgciの代わりにGet-ChildItemを使用エイリアスは対話型シェル使用では許可される。
    • ?whereの代わりにWhere-Objectを使用
    • %の代わりにForEach-Objectを使用
    • lsdirの代わりにGet-ChildItemを使用

完全な例:エンドツーエンドコマンドレットパターン

function New-Resource {
    [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
    param(
        [Parameter(Mandatory = $true,
                   ValueFromPipeline = $true,
                   ValueFromPipelineByPropertyName = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Name,

        [Parameter()]
        [ValidateSet('Development', 'Production')]
        [string]$Environment = 'Development'
    )
    
    begin {
        Write-Verbose "リソース作成プロセスを開始します"
    }
    
    process {
        try {
            if ($PSCmdlet.ShouldProcess($Name, "新しいリソースを作成")) {
                # リソース作成ロジックをここに記述
                Write-Output ([PSCustomObject]@{
                    Name = $Name
                    Environment = $Environment
                    Created = Get-Date
                })
            }
        }
        catch {
            Write-Error "リソース作成に失敗しました: $_"
        }
    }
    
    end {
        Write-Verbose "リソース作成プロセスが完了しました"
    }
}