Windows PowerShell グローバル変数の完全ガイド – スコープを理解して変数を使いこなす

Windows

「関数の中で設定した変数が、外で使えない!」 「スクリプト全体で共有したい値があるのに…」 「グローバル変数って聞くけど、どう使うの?」

PowerShellでスクリプトを書いていると、こんな悩みに直面することがありますよね。

実は、PowerShellの変数には「スコープ」という概念があり、変数が使える範囲が決まっているんです。グローバル変数を理解すれば、スクリプト全体で値を共有したり、関数間でデータを受け渡したりが自在にできるようになります。

今回は、PowerShellのグローバル変数について、基本から実践的な使い方まで、分かりやすく解説していきます!


スポンサーリンク

PowerShellの変数スコープとは?

スコープの基本概念

スコープとは、変数が有効な範囲のことです。

部屋に例えると:

  • ローカルスコープ = 自分の部屋(その場所でのみ有効)
  • スクリプトスコープ = 家全体(スクリプト内で有効)
  • グローバルスコープ = 街全体(PowerShellセッション全体で有効)

PowerShellの4つのスコープ

# スコープの種類と優先順位(上から順に狭い範囲)
1. Local(ローカル)    # 現在の場所のみ
2. Script(スクリプト)  # スクリプトファイル内
3. Global(グローバル)  # PowerShellセッション全体
4. Private(プライベート)# 子スコープから見えない

スコープの確認方法:

# 現在のスコープを確認
Get-Variable -Scope Local
Get-Variable -Scope Global
Get-Variable -Scope Script

グローバル変数の作成と使用方法

基本的な作成方法

方法1:$global:プレフィックスを使う

# グローバル変数の作成
$global:MyGlobalVar = "これはグローバル変数です"

# グローバル変数の参照
Write-Host $global:MyGlobalVar

# 通常の参照でもアクセス可能
Write-Host $MyGlobalVar

方法2:New-Variableコマンドレットを使う

# コマンドレットでグローバル変数を作成
New-Variable -Name "AppConfig" -Value "Production" -Scope Global

# オプション付きで作成(読み取り専用)
New-Variable -Name "AppVersion" -Value "1.0.0" -Scope Global -Option ReadOnly

ローカル変数との違いを理解する

# 実験:スコープの違いを確認
function Test-Scope {
    # ローカル変数(関数内のみ有効)
    $localVar = "ローカル変数"
    
    # グローバル変数(どこでも有効)
    $global:globalVar = "グローバル変数"
    
    Write-Host "関数内 - ローカル: $localVar"
    Write-Host "関数内 - グローバル: $globalVar"
}

# 関数を実行
Test-Scope

# 関数の外で確認
Write-Host "関数外 - ローカル: $localVar"  # 空(アクセス不可)
Write-Host "関数外 - グローバル: $globalVar"  # 表示される

グローバル変数の実践的な使い方

設定値の管理

# アプリケーション全体の設定をグローバル変数で管理
function Initialize-AppSettings {
    $global:AppSettings = @{
        DatabaseServer = "localhost\SQLEXPRESS"
        LogPath = "C:\Logs"
        DebugMode = $true
        MaxRetries = 3
        Timeout = 30
    }
    
    Write-Host "アプリケーション設定を初期化しました" -ForegroundColor Green
}

# 設定を使う関数
function Write-AppLog {
    param([string]$Message)
    
    if ($global:AppSettings.DebugMode) {
        $logFile = Join-Path $global:AppSettings.LogPath "app_$(Get-Date -Format 'yyyyMMdd').log"
        $logEntry = "$(Get-Date -Format 'HH:mm:ss'): $Message"
        Add-Content -Path $logFile -Value $logEntry
        Write-Host $logEntry -ForegroundColor Yellow
    }
}

# 使用例
Initialize-AppSettings
Write-AppLog "アプリケーションを開始しました"

カウンターや累積値の管理

# 処理回数をカウントするグローバル変数
$global:ProcessCount = 0
$global:ErrorCount = 0
$global:SuccessCount = 0

function Process-Item {
    param([string]$Item)
    
    $global:ProcessCount++
    
    try {
        # 何かの処理
        if ($Item -match "error") {
            throw "エラーが発生しました"
        }
        
        Write-Host "処理成功: $Item" -ForegroundColor Green
        $global:SuccessCount++
    }
    catch {
        Write-Host "処理失敗: $Item - $_" -ForegroundColor Red
        $global:ErrorCount++
    }
}

# 複数アイテムを処理
@("item1", "error_item", "item3", "error_item2", "item5") | ForEach-Object {
    Process-Item $_
}

# 結果を表示
Write-Host "`n処理結果:"
Write-Host "総処理数: $global:ProcessCount"
Write-Host "成功: $global:SuccessCount" -ForegroundColor Green
Write-Host "失敗: $global:ErrorCount" -ForegroundColor Red

複数スクリプト間での値共有

Script1.ps1:

# データを収集してグローバル変数に保存
$global:CollectedData = @()

function Collect-SystemInfo {
    $info = @{
        ComputerName = $env:COMPUTERNAME
        OS = (Get-CimInstance Win32_OperatingSystem).Caption
        Memory = (Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory / 1GB
        Timestamp = Get-Date
    }
    
    $global:CollectedData += $info
    Write-Host "システム情報を収集しました"
}

Collect-SystemInfo

Script2.ps1:

# 別のスクリプトから、グローバル変数のデータを利用
function Export-CollectedData {
    if ($global:CollectedData) {
        $global:CollectedData | Export-Csv -Path "C:\Reports\system_info.csv" -NoTypeInformation
        Write-Host "データをエクスポートしました"
    } else {
        Write-Host "エクスポートするデータがありません" -ForegroundColor Yellow
    }
}

Export-CollectedData

環境変数との違いと使い分け

環境変数とグローバル変数の比較

# 環境変数(システム全体またはユーザー全体で永続的)
$env:MY_ENV_VAR = "環境変数の値"
[Environment]::SetEnvironmentVariable("MY_ENV_VAR", "環境変数の値", "User")

# グローバル変数(PowerShellセッション内のみ)
$global:MY_GLOBAL_VAR = "グローバル変数の値"

# 違いを確認
Write-Host "環境変数: $env:MY_ENV_VAR"
Write-Host "グローバル変数: $global:MY_GLOBAL_VAR"

# 新しいPowerShellウィンドウを開くと...
# 環境変数は残っているが、グローバル変数は消えている

使い分けの指針

環境変数を使うべき場合:

  • システム設定(PATH、TEMP など)
  • 複数のアプリケーション間で共有
  • PowerShellセッション終了後も保持したい

グローバル変数を使うべき場合:

  • スクリプト実行中のみ必要な値
  • 一時的な設定やカウンター
  • セッション内での作業データ

グローバル変数のベストプラクティス

命名規則を決める

# 良い例:プレフィックスで用途を明確に
$global:CONFIG_DatabasePath = "C:\Database"
$global:TEMP_ProcessingData = @()
$global:APP_Version = "2.0.1"

# グローバル変数用のプレフィックス例
# CONFIG_ : 設定値
# TEMP_   : 一時データ
# APP_    : アプリケーション情報
# LOG_    : ログ関連

初期化関数を作る

function Initialize-GlobalVariables {
    [CmdletBinding()]
    param()
    
    # 既存の値をクリア(オプション)
    if ($global:APP_Initialized) {
        Write-Host "グローバル変数は既に初期化されています" -ForegroundColor Yellow
        return
    }
    
    # グローバル変数を初期化
    $global:APP_Initialized = $true
    $global:APP_StartTime = Get-Date
    $global:APP_Config = @{
        Version = "1.0.0"
        Environment = "Development"
        MaxThreads = 4
    }
    $global:APP_Statistics = @{
        TotalRuns = 0
        Errors = @()
        LastRun = $null
    }
    
    Write-Host "グローバル変数を初期化しました" -ForegroundColor Green
    Write-Host "バージョン: $($global:APP_Config.Version)"
    Write-Host "環境: $($global:APP_Config.Environment)"
}

# スクリプトの最初で呼び出す
Initialize-GlobalVariables

クリーンアップを忘れない

function Clear-GlobalVariables {
    # 特定のプレフィックスを持つグローバル変数をクリア
    Get-Variable -Scope Global | Where-Object {
        $_.Name -match "^(APP_|TEMP_|CONFIG_)"
    } | ForEach-Object {
        Remove-Variable -Name $_.Name -Scope Global -Force -ErrorAction SilentlyContinue
        Write-Host "削除: $($_.Name)" -ForegroundColor Gray
    }
    
    Write-Host "グローバル変数をクリーンアップしました" -ForegroundColor Green
}

# スクリプトの最後やエラー時に実行
try {
    # メイン処理
} finally {
    Clear-GlobalVariables
}

よくあるトラブルと解決方法

トラブル1:変数が見つからない

問題:

function Set-Value {
    $myVar = "テスト"  # ローカル変数になってしまう
}

Set-Value
Write-Host $myVar  # 空

解決:

function Set-Value {
    $global:myVar = "テスト"  # グローバル変数として設定
}

Set-Value
Write-Host $myVar  # "テスト"が表示される

トラブル2:予期しない値の上書き

問題を防ぐ方法:

# 読み取り専用のグローバル変数を作成
New-Variable -Name "CONST_MaxSize" -Value 100 -Scope Global -Option ReadOnly

# 定数として扱う(変更不可)
try {
    $global:CONST_MaxSize = 200  # エラーになる
} catch {
    Write-Host "定数は変更できません: $_" -ForegroundColor Red
}

トラブル3:モジュール間での変数共有

# モジュール内でグローバル変数を設定
# MyModule.psm1
function Set-ModuleGlobal {
    $global:ModuleData = "モジュールから設定"
    
    # モジュール変数(モジュール内のみ)
    $script:ModuleInternal = "内部データ"
}

# メインスクリプト
Import-Module .\MyModule.psm1
Set-ModuleGlobal
Write-Host $global:ModuleData  # アクセス可能
Write-Host $script:ModuleInternal  # アクセス不可

実践例:プロジェクト管理スクリプト

完全な実装例

# プロジェクト管理用グローバル変数システム

# 初期化
function Initialize-ProjectManager {
    $global:PROJECT = @{
        Name = "MyProject"
        Tasks = @()
        TeamMembers = @()
        StartDate = Get-Date
        Status = "Active"
        Statistics = @{
            TotalTasks = 0
            CompletedTasks = 0
            PendingTasks = 0
        }
    }
    
    Write-Host "プロジェクト管理システムを初期化しました" -ForegroundColor Green
}

# タスク追加
function Add-ProjectTask {
    param(
        [string]$TaskName,
        [string]$Assignee,
        [string]$Priority = "Normal"
    )
    
    $task = @{
        ID = $global:PROJECT.Statistics.TotalTasks + 1
        Name = $TaskName
        Assignee = $Assignee
        Priority = $Priority
        Status = "Pending"
        CreatedDate = Get-Date
    }
    
    $global:PROJECT.Tasks += $task
    $global:PROJECT.Statistics.TotalTasks++
    $global:PROJECT.Statistics.PendingTasks++
    
    Write-Host "タスクを追加: #$($task.ID) - $TaskName" -ForegroundColor Cyan
}

# タスク完了
function Complete-ProjectTask {
    param([int]$TaskID)
    
    $task = $global:PROJECT.Tasks | Where-Object { $_.ID -eq $TaskID }
    if ($task) {
        $task.Status = "Completed"
        $task.CompletedDate = Get-Date
        
        $global:PROJECT.Statistics.CompletedTasks++
        $global:PROJECT.Statistics.PendingTasks--
        
        Write-Host "タスク完了: #$TaskID - $($task.Name)" -ForegroundColor Green
    } else {
        Write-Host "タスクが見つかりません: #$TaskID" -ForegroundColor Red
    }
}

# レポート表示
function Show-ProjectReport {
    Write-Host "`n===== プロジェクトレポート =====" -ForegroundColor Yellow
    Write-Host "プロジェクト名: $($global:PROJECT.Name)"
    Write-Host "ステータス: $($global:PROJECT.Status)"
    Write-Host "開始日: $($global:PROJECT.StartDate.ToString('yyyy/MM/dd'))"
    Write-Host ""
    Write-Host "タスク統計:"
    Write-Host "  総タスク数: $($global:PROJECT.Statistics.TotalTasks)"
    Write-Host "  完了: $($global:PROJECT.Statistics.CompletedTasks)" -ForegroundColor Green
    Write-Host "  保留中: $($global:PROJECT.Statistics.PendingTasks)" -ForegroundColor Yellow
    
    if ($global:PROJECT.Statistics.TotalTasks -gt 0) {
        $completionRate = ($global:PROJECT.Statistics.CompletedTasks / $global:PROJECT.Statistics.TotalTasks) * 100
        Write-Host "  完了率: $([math]::Round($completionRate, 1))%"
    }
    
    Write-Host "`nタスク一覧:"
    $global:PROJECT.Tasks | ForEach-Object {
        $statusColor = if ($_.Status -eq "Completed") { "Green" } else { "Gray" }
        Write-Host "  #$($_.ID): $($_.Name) [$($_.Assignee)] - $($_.Status)" -ForegroundColor $statusColor
    }
}

# 使用例
Initialize-ProjectManager
Add-ProjectTask -TaskName "要件定義" -Assignee "田中" -Priority "High"
Add-ProjectTask -TaskName "設計書作成" -Assignee "佐藤" -Priority "High"
Add-ProjectTask -TaskName "実装" -Assignee "鈴木" -Priority "Normal"
Complete-ProjectTask -TaskID 1
Show-ProjectReport

PowerShell ISEやVS Codeでの注意点

デバッグ時の動作

# ISEやVS Codeでは、セッションが継続される
# 同じグローバル変数が残り続けることがある

# デバッグ前にクリアする習慣
function Reset-DebugEnvironment {
    # すべてのカスタムグローバル変数を削除
    Get-Variable -Scope Global | Where-Object {
        $_.Name -notin @('PSVersionTable', 'PSScriptRoot', 'PSCommandPath', 
                        'Host', 'HOME', 'ExecutionContext', 'Error')
    } | Where-Object {
        -not $_.Name.StartsWith('$')
    } | ForEach-Object {
        Remove-Variable -Name $_.Name -Scope Global -Force -ErrorAction SilentlyContinue
    }
    
    Write-Host "デバッグ環境をリセットしました" -ForegroundColor Cyan
}

まとめ – グローバル変数を正しく使いこなそう

PowerShellのグローバル変数について、基本から実践まで理解できましたか?

押さえておくべきポイント

✅ **$global:**プレフィックスで、どこからでもアクセス可能な変数を作成
スコープの理解が、変数管理の基本
命名規則を決めて、管理しやすくする
初期化とクリーンアップで、クリーンな環境を保つ

グローバル変数が適している場面

  • 設定値の一元管理
  • スクリプト全体での状態管理
  • 関数間でのデータ共有
  • カウンターや統計情報の収集

今すぐ実践できること

  1. 既存スクリプトの変数スコープを見直す
  2. 設定値をグローバル変数で管理する
  3. 命名規則を決めて適用する
  4. 初期化・クリーンアップ関数を作成する

グローバル変数を適切に使いこなせば、より柔軟で保守しやすいPowerShellスクリプトが書けるようになります。ぜひ今日から実践してみてください!

コメント

タイトルとURLをコピーしました