WindowsServer 2025 総合ガイド 第04回

記事内に広告が含まれています。

WindowsServer 2025 総合ガイド 第04回
PowerShellスクリプティング基礎 ― 自動化への第一歩

第3回では、PowerShellを使ったファイル・フォルダ操作、ディスク管理、ローカルユーザーとグループの管理を学びました。第4回となる今回は、PowerShellスクリプティングの基礎を学びます。変数、データ型、条件分岐、ループ処理、関数の定義、そしてエラーハンドリングまで、自動化スクリプトを作成するために必要な知識を習得しましょう。

4.1 この記事で学ぶこと

  • 変数とデータ型を理解し、使用できる
  • 条件分岐とループ処理を記述できる
  • 関数を定義し、スクリプトファイルを作成できる

4.2 前提条件

  • 第3回完了(PowerShellの基本操作が可能)
  • Windows Server 2025にリモートデスクトップ接続できる状態
  • PowerShell 7.4を管理者として起動できる状態

4.3 変数の基礎

プログラミングにおいて「変数」は、データを一時的に保存しておく箱のようなものです。PowerShellでは、変数を使うことで、コマンドの実行結果を保存したり、繰り返し使う値を管理したりできます。

4.3.1 変数の宣言と代入

PowerShellでは、変数名の前に $(ドル記号)を付けて変数を定義します。

[実行環境: PowerShell 7.4 (管理者)]

# 変数に値を代入
$message = "Hello, PowerShell!"
$number = 42
$isEnabled = $true

# 変数の値を表示
$message
$number
$isEnabled

実行結果の例:

Hello, PowerShell!
42
True

変数名の命名規則

変数名には以下のルールがあります。

  • 英数字とアンダースコア(_)が使用可能
  • 大文字小文字を区別しない($Name$name は同じ変数)
  • 数字で始めることはできない
  • スペースや特殊文字は使用できない(ただし ${変数名} の形式なら可能)

可読性のために、以下のような命名規則を推奨します。

スタイル 説明
キャメルケース $userName 最初の単語は小文字、以降の単語は大文字で始める
パスカルケース $UserName すべての単語を大文字で始める

本シリーズでは、ローカル変数にはキャメルケース、グローバル変数やパラメータにはパスカルケースを使用します。

4.3.2 データ型

PowerShellは動的型付け言語であり、変数に代入した値によって自動的にデータ型が決まります。主要なデータ型を紹介します。

データ型 .NET型名 説明
文字列 [String] "Hello" テキストデータ
整数 [Int32] 42 32ビット整数(約±21億)
長整数 [Int64] 9999999999 64ビット整数
小数 [Double] 3.14 倍精度浮動小数点数
真偽値 [Boolean] $true, $false 真または偽
配列 [Array] @(1, 2, 3) 複数の値を格納
ハッシュテーブル [Hashtable] @{Key = "Value"} キーと値のペア

4.3.3 型の確認と変換

GetType()メソッド

変数のデータ型を確認するには、GetType()メソッドを使用します。

[実行環境: PowerShell 7.4 (管理者)]

# 各変数の型を確認
$text = "Hello"
$num = 100
$decimal = 3.14
$flag = $true

$text.GetType().Name
$num.GetType().Name
$decimal.GetType().Name
$flag.GetType().Name

実行結果の例:

String
Int32
Double
Boolean

型のキャスト(変換)

明示的に型を指定するには、型名を角括弧で囲んで変数の前に置きます。

# 文字列を整数に変換
[int]$stringToInt = "123"
$stringToInt.GetType().Name  # Int32

# 整数を文字列に変換
[string]$intToString = 456
$intToString.GetType().Name  # String

# 小数を整数に変換(小数点以下は切り捨て)
[int]$doubleToInt = 3.7
$doubleToInt  # 4(四捨五入される)

注意:変換できない値をキャストしようとするとエラーになります。例えば、[int]"abc" はエラーになります。

4.3.4 特殊変数

PowerShellには、システムが自動的に設定する特殊な変数があります。

変数 説明
$null 値が存在しないことを表す
$true 真偽値の「真」
$false 真偽値の「偽」
$_ パイプラインの現在のオブジェクト
$PSVersionTable PowerShellのバージョン情報
$HOME ユーザーのホームディレクトリ
$PWD 現在の作業ディレクトリ
$Error 直近のエラー情報を格納する配列

[実行環境: PowerShell 7.4 (管理者)]

# 特殊変数の例
$PSVersionTable.PSVersion  # PowerShellのバージョン
$HOME                       # ホームディレクトリ
$PWD                        # 現在のディレクトリ

実行結果の例:

Major  Minor  Patch  PreReleaseLabel BuildLabel
-----  -----  -----  --------------- ----------
7      4      7

C:\Users\Administrator
C:\Users\Administrator

4.4 文字列操作

サーバー管理では、ログメッセージの生成、設定ファイルの編集、レポートの作成など、文字列を扱う場面が多くあります。PowerShellでの文字列操作を学びましょう。

4.4.1 文字列の結合

文字列を結合するにはいくつかの方法があります。

[実行環境: PowerShell 7.4 (管理者)]

# 方法1: + 演算子
$firstName = "Taro"
$lastName = "Yamada"
$fullName = $firstName + " " + $lastName
$fullName  # Taro Yamada

# 方法2: -join 演算子
$parts = @("2025", "01", "20")
$date = $parts -join "-"
$date  # 2025-01-20

# 方法3: -f 演算子(フォーマット文字列)
$name = "Server01"
$status = "Running"
$message = "サーバー {0} の状態: {1}" -f $name, $status
$message  # サーバー Server01 の状態: Running

4.4.2 変数展開(ダブルクォート vs シングルクォート)

PowerShellでは、ダブルクォート(")とシングルクォート(')で文字列の扱いが異なります。

[実行環境: PowerShell 7.4 (管理者)]

$serverName = "WS2025-01"

# ダブルクォート:変数が展開される
"サーバー名: $serverName"  # サーバー名: WS2025-01

# シングルクォート:変数が展開されない(リテラル文字列)
'サーバー名: $serverName'  # サーバー名: $serverName

サブ式演算子

ダブルクォート内で複雑な式を展開するには、$()(サブ式演算子)を使用します。

# プロパティやメソッドを展開する場合
$service = Get-Service -Name W32Time
"サービス状態: $($service.Status)"

# 計算結果を展開する場合
$a = 10
$b = 20
"合計: $($a + $b)"  # 合計: 30

4.4.3 ヒアストリング(複数行文字列)

複数行にわたる文字列を定義するには、ヒアストリングを使用します。

[実行環境: PowerShell 7.4 (管理者)]

# 変数展開ありのヒアストリング
$serverName = "WS2025-01"
$multiLine = @"
サーバー情報レポート
====================
サーバー名: $serverName
作成日時: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")
"@

$multiLine

実行結果の例:

サーバー情報レポート
====================
サーバー名: WS2025-01
作成日時: 2025-01-20 10:30:45
# 変数展開なしのヒアストリング(リテラル)
$literal = @'
これは $変数 が展開されません。
$(コマンド) も実行されません。
'@

$literal

注意:ヒアストリングの開始記号(@" または @')の後ろには何も記述できません。また、終了記号("@ または '@)は行頭に置く必要があります。

4.4.4 文字列メソッド

文字列オブジェクトには、便利なメソッドが多数用意されています。

[実行環境: PowerShell 7.4 (管理者)]

$text = "  Hello, Windows Server 2025!  "

# 大文字・小文字変換
$text.ToUpper()  # "  HELLO, WINDOWS SERVER 2025!  "
$text.ToLower()  # "  hello, windows server 2025!  "

# 文字列の検索
$text.Contains("Server")   # True
$text.Contains("Linux")    # False
$text.StartsWith("  Hello") # True
$text.EndsWith("!  ")      # True

# 文字列の置換
$text.Replace("2025", "2026")  # "  Hello, Windows Server 2026!  "

# 空白の除去
$text.Trim()       # "Hello, Windows Server 2025!"(前後の空白を除去)
$text.TrimStart()  # "Hello, Windows Server 2025!  "(前の空白を除去)
$text.TrimEnd()    # "  Hello, Windows Server 2025!"(後の空白を除去)

# 文字列の分割
"apple,banana,cherry".Split(",")  # @("apple", "banana", "cherry")

# 部分文字列の取得
"PowerShell".Substring(0, 5)  # "Power"
"PowerShell".Substring(5)     # "Shell"

4.5 配列とハッシュテーブル

複数のデータをまとめて扱うには、配列やハッシュテーブルを使用します。

4.5.1 配列の作成とアクセス

配列は、複数の値を順序付けて格納するデータ構造です。

[実行環境: PowerShell 7.4 (管理者)]

# 配列の作成方法
$servers = @("Server01", "Server02", "Server03")
$numbers = 1, 2, 3, 4, 5  # @() は省略可能
$empty = @()  # 空の配列

# 配列の要素数
$servers.Count  # 3

# インデックスによるアクセス(0から始まる)
$servers[0]   # Server01(最初の要素)
$servers[1]   # Server02(2番目の要素)
$servers[-1]  # Server03(最後の要素)

# 範囲指定
$servers[0..1]  # @("Server01", "Server02")

配列への要素追加

# 要素の追加
$servers += "Server04"
$servers  # @("Server01", "Server02", "Server03", "Server04")

パフォーマンスの注意:+= 演算子は、実際には新しい配列を作成して全要素をコピーします。大量の要素を追加する場合は、System.Collections.ArrayListSystem.Collections.Generic.List の使用を検討してください。

foreachでの繰り返し処理

# 配列の各要素に対して処理
$servers = @("Server01", "Server02", "Server03")
foreach ($server in $servers) {
    Write-Host "Processing: $server"
}

実行結果の例:

Processing: Server01
Processing: Server02
Processing: Server03

4.5.2 ハッシュテーブルの作成とアクセス

ハッシュテーブルは、キーと値のペアでデータを格納するデータ構造です。設定情報やプロパティの管理に便利です。

[実行環境: PowerShell 7.4 (管理者)]

# ハッシュテーブルの作成
$serverInfo = @{
    Name = "WS2025-01"
    IPAddress = "192.168.1.10"
    Role = "WebServer"
    IsProduction = $true
}

# 値へのアクセス方法
$serverInfo["Name"]       # WS2025-01(ブラケット記法)
$serverInfo.IPAddress     # 192.168.1.10(ドット記法)

# 値の変更
$serverInfo.Role = "AppServer"

# キーと値の追加
$serverInfo["OS"] = "Windows Server 2025"
$serverInfo.Memory = "16GB"

# キーの存在確認
$serverInfo.ContainsKey("Name")  # True
$serverInfo.ContainsKey("CPU")   # False

# すべてのキーと値を取得
$serverInfo.Keys    # すべてのキー
$serverInfo.Values  # すべての値

ハッシュテーブルの表示

# ハッシュテーブルの内容を表示
$serverInfo | Format-Table -AutoSize

実行結果の例:

Name            Value
----            -----
Name            WS2025-01
IPAddress       192.168.1.10
Role            AppServer
IsProduction    True
OS              Windows Server 2025
Memory          16GB

4.6 条件分岐

条件に応じて異なる処理を実行するには、条件分岐を使用します。

4.6.1 比較演算子

PowerShellの比較演算子は、他の言語とは異なる表記を使用します。

演算子 意味
-eq 等しい(equal) 5 -eq 5 → True
-ne 等しくない(not equal) 5 -ne 3 → True
-gt より大きい(greater than) 5 -gt 3 → True
-ge 以上(greater or equal) 5 -ge 5 → True
-lt より小さい(less than) 3 -lt 5 → True
-le 以下(less or equal) 5 -le 5 → True

パターンマッチング演算子

演算子 意味
-like ワイルドカードパターンに一致 "Server01" -like "Server*" → True
-notlike ワイルドカードパターンに一致しない "Server01" -notlike "Web*" → True
-match 正規表現に一致 "Server01" -match "Server\d+" → True
-notmatch 正規表現に一致しない "Server01" -notmatch "^\d+" → True

コレクション演算子

演算子 意味
-contains 配列が値を含む @(1,2,3) -contains 2 → True
-notcontains 配列が値を含まない @(1,2,3) -notcontains 5 → True
-in 値が配列に含まれる 2 -in @(1,2,3) → True
-notin 値が配列に含まれない 5 -notin @(1,2,3) → True

4.6.2 論理演算子

複数の条件を組み合わせるには論理演算子を使用します。

演算子 意味
-and 両方が真 ($a -gt 0) -and ($a -lt 10)
-or どちらかが真 ($a -eq 0) -or ($a -eq 1)
-not / ! 否定 -not $false / !$false

4.6.3 if文

最も基本的な条件分岐は if 文です。

[実行環境: PowerShell 7.4 (管理者)]

# 基本的なif文
$diskUsage = 85

if ($diskUsage -ge 90) {
    Write-Host "警告: ディスク使用率が危険水準です!" -ForegroundColor Red
}
elseif ($diskUsage -ge 80) {
    Write-Host "注意: ディスク使用率が高くなっています。" -ForegroundColor Yellow
}
else {
    Write-Host "正常: ディスク使用率は問題ありません。" -ForegroundColor Green
}

実行結果の例:

注意: ディスク使用率が高くなっています。

実践例:サービス状態のチェック

# サービスの状態をチェックして適切なメッセージを表示
$service = Get-Service -Name "W32Time"

if ($service.Status -eq "Running") {
    Write-Host "$($service.Name) は正常に実行中です。" -ForegroundColor Green
}
elseif ($service.Status -eq "Stopped") {
    Write-Host "$($service.Name) は停止しています。" -ForegroundColor Yellow
}
else {
    Write-Host "$($service.Name) の状態: $($service.Status)" -ForegroundColor Cyan
}

4.6.4 switch文

複数の条件を効率的に処理するには switch 文を使用します。

[実行環境: PowerShell 7.4 (管理者)]

# 基本的なswitch文
$dayOfWeek = (Get-Date).DayOfWeek

switch ($dayOfWeek) {
    "Monday"    { Write-Host "月曜日です。週の始まり!" }
    "Tuesday"   { Write-Host "火曜日です。" }
    "Wednesday" { Write-Host "水曜日です。週の折り返し。" }
    "Thursday"  { Write-Host "木曜日です。" }
    "Friday"    { Write-Host "金曜日です。もうすぐ週末!" }
    "Saturday"  { Write-Host "土曜日です。休日!" }
    "Sunday"    { Write-Host "日曜日です。休日!" }
    default     { Write-Host "不明な曜日です。" }
}

ワイルドカードと正規表現の使用

# -Wildcard オプション
$fileName = "report_2025.xlsx"

switch -Wildcard ($fileName) {
    "*.xlsx" { Write-Host "Excelファイルです。" }
    "*.docx" { Write-Host "Wordファイルです。" }
    "*.pdf"  { Write-Host "PDFファイルです。" }
    default  { Write-Host "その他のファイルです。" }
}

# -Regex オプション
$ipAddress = "192.168.1.100"

switch -Regex ($ipAddress) {
    "^10\."      { Write-Host "クラスAプライベートアドレスです。" }
    "^172\.(1[6-9]|2[0-9]|3[0-1])\." { Write-Host "クラスBプライベートアドレスです。" }
    "^192\.168\." { Write-Host "クラスCプライベートアドレスです。" }
    default      { Write-Host "パブリックアドレスの可能性があります。" }
}

4.6.5 三項演算子(PowerShell 7以降)

PowerShell 7以降では、三項演算子(条件演算子)が使用できます。

[実行環境: PowerShell 7.4 (管理者)]

# 三項演算子: 条件 ? 真の場合 : 偽の場合
$isProduction = $true
$environment = $isProduction ? "本番環境" : "開発環境"
$environment  # 本番環境

# 従来のif文での記述(比較用)
if ($isProduction) {
    $environment = "本番環境"
} else {
    $environment = "開発環境"
}

補足:三項演算子はPowerShell 7以降の機能です。Windows PowerShell 5.1では使用できません。

4.7 ループ処理

同じ処理を繰り返し実行するには、ループ処理を使用します。

4.7.1 foreach文

コレクション(配列など)の各要素に対して処理を行います。

[実行環境: PowerShell 7.4 (管理者)]

# 配列の各要素を処理
$services = @("W32Time", "Spooler", "WinRM")

foreach ($serviceName in $services) {
    $service = Get-Service -Name $serviceName
    Write-Host "$serviceName : $($service.Status)"
}

実行結果の例:

W32Time : Running
Spooler : Running
WinRM : Running

4.7.2 for文

カウンタを使った繰り返し処理に適しています。

[実行環境: PowerShell 7.4 (管理者)]

# 1から5まで繰り返し
for ($i = 1; $i -le 5; $i++) {
    Write-Host "カウント: $i"
}

実行結果の例:

カウント: 1
カウント: 2
カウント: 3
カウント: 4
カウント: 5

配列のインデックスを使ったアクセス

# インデックスを使って配列にアクセス
$servers = @("Server01", "Server02", "Server03")

for ($i = 0; $i -lt $servers.Count; $i++) {
    Write-Host "サーバー $($i + 1): $($servers[$i])"
}

4.7.3 while文とdo-while文

条件が真の間、処理を繰り返します。

[実行環境: PowerShell 7.4 (管理者)]

# while文:条件を先に評価
$count = 1
while ($count -le 3) {
    Write-Host "while: $count"
    $count++
}

# do-while文:処理を先に実行してから条件を評価
$count = 1
do {
    Write-Host "do-while: $count"
    $count++
} while ($count -le 3)

実践例:サービス起動の待機

# サービスが起動するまで待機(最大30秒)
$serviceName = "W32Time"
$maxWait = 30
$waited = 0

while ((Get-Service -Name $serviceName).Status -ne "Running" -and $waited -lt $maxWait) {
    Write-Host "サービスの起動を待機中... ($waited 秒)"
    Start-Sleep -Seconds 1
    $waited++
}

if ((Get-Service -Name $serviceName).Status -eq "Running") {
    Write-Host "サービスが起動しました。"
} else {
    Write-Host "タイムアウト: サービスが起動しませんでした。"
}

4.7.4 ForEach-Objectコマンドレット

パイプラインで使用するループ処理です。

[実行環境: PowerShell 7.4 (管理者)]

# パイプラインでForEach-Objectを使用
Get-Service | Where-Object { $_.Status -eq "Running" } | ForEach-Object {
    Write-Host "実行中: $($_.Name)"
} | Select-Object -First 5

簡略構文

# $_ は現在のオブジェクトを表す
1..5 | ForEach-Object { $_ * 2 }  # 2, 4, 6, 8, 10

並列処理(PowerShell 7以降)

PowerShell 7以降では、-Parallel パラメータで並列処理が可能です。

# 並列処理(大量のデータ処理時に有効)
$servers = @("Server01", "Server02", "Server03", "Server04", "Server05")

$servers | ForEach-Object -Parallel {
    Write-Host "Processing: $_"
    Start-Sleep -Seconds 1  # 何らかの処理をシミュレート
} -ThrottleLimit 3  # 同時実行数を制限

補足:-Parallel はPowerShell 7以降の機能です。並列処理内では、外部の変数に直接アクセスできない点に注意してください($using: スコープ修飾子を使用)。

4.7.5 ループ制御(break、continue)

ループの実行を制御するキーワードです。

[実行環境: PowerShell 7.4 (管理者)]

# break:ループを完全に終了
foreach ($i in 1..10) {
    if ($i -eq 5) {
        Write-Host "5でループを終了"
        break
    }
    Write-Host "数値: $i"
}
# 出力: 1, 2, 3, 4 の後に "5でループを終了"

# continue:現在の反復をスキップして次へ
foreach ($i in 1..5) {
    if ($i -eq 3) {
        continue  # 3をスキップ
    }
    Write-Host "数値: $i"
}
# 出力: 1, 2, 4, 5(3はスキップ)

4.8 関数の定義

繰り返し使用する処理は、関数として定義することで再利用できます。

4.8.1 関数の基本構文

[実行環境: PowerShell 7.4 (管理者)]

# 基本的な関数の定義
function Get-Greeting {
    return "Hello, PowerShell!"
}

# 関数の呼び出し
Get-Greeting  # Hello, PowerShell!

パラメータの定義

# パラメータを持つ関数
function Get-Greeting {
    param (
        [string]$Name
    )
    return "Hello, $Name!"
}

# パラメータを指定して呼び出し
Get-Greeting -Name "Administrator"  # Hello, Administrator!
Get-Greeting "Administrator"         # 位置パラメータでも可

4.8.2 戻り値(return)

PowerShellでは、関数内で出力されたすべての値が戻り値となります。return は明示的に値を返し、関数を終了します。

[実行環境: PowerShell 7.4 (管理者)]

# 戻り値の例
function Get-DiskUsage {
    param (
        [string]$DriveLetter = "C"
    )
    
    $volume = Get-Volume -DriveLetter $DriveLetter
    $usedPercent = [math]::Round((($volume.Size - $volume.SizeRemaining) / $volume.Size) * 100, 1)
    
    return $usedPercent
}

$usage = Get-DiskUsage -DriveLetter "C"
Write-Host "Cドライブ使用率: $usage%"

4.8.3 パラメータの詳細設定

型指定とデフォルト値

[実行環境: PowerShell 7.4 (管理者)]

function Test-ServiceStatus {
    param (
        [string]$ServiceName = "W32Time",  # デフォルト値
        [int]$TimeoutSeconds = 30           # デフォルト値
    )
    
    $service = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
    
    if ($null -eq $service) {
        return "サービス '$ServiceName' が見つかりません。"
    }
    
    return "サービス '$ServiceName' の状態: $($service.Status)"
}

# デフォルト値を使用
Test-ServiceStatus

# パラメータを指定
Test-ServiceStatus -ServiceName "Spooler" -TimeoutSeconds 60

必須パラメータ

function New-ServerReport {
    param (
        [Parameter(Mandatory)]  # 必須パラメータ
        [string]$ServerName,
        
        [Parameter(Mandatory)]
        [string]$ReportPath
    )
    
    Write-Host "サーバー: $ServerName のレポートを $ReportPath に作成します。"
}

# 必須パラメータを省略するとプロンプトが表示される
# New-ServerReport

ValidateSet による値の制限

function Set-Environment {
    param (
        [Parameter(Mandatory)]
        [ValidateSet("Development", "Staging", "Production")]
        [string]$Environment
    )
    
    Write-Host "環境を '$Environment' に設定しました。"
}

Set-Environment -Environment "Production"  # OK
# Set-Environment -Environment "Test"      # エラー: 許可されていない値

4.8.4 スコープの概念

変数にはスコープ(有効範囲)があります。

[実行環境: PowerShell 7.4 (管理者)]

# グローバルスコープとローカルスコープ
$globalVar = "グローバル変数"

function Test-Scope {
    $localVar = "ローカル変数"
    
    Write-Host "関数内から見たグローバル変数: $globalVar"
    Write-Host "関数内から見たローカル変数: $localVar"
}

Test-Scope
Write-Host "関数外から見たグローバル変数: $globalVar"
# Write-Host "関数外から見たローカル変数: $localVar"  # エラー: 存在しない

グローバル変数の明示的な指定

# 関数内からグローバル変数を変更
$counter = 0

function Increment-Counter {
    $global:counter++
}

Increment-Counter
Increment-Counter
Write-Host "カウンター: $counter"  # 2

ベストプラクティス:グローバル変数の多用は避け、パラメータと戻り値を使って関数間でデータを受け渡すことを推奨します。

4.9 スクリプトファイルの作成

ここまで学んだ内容を組み合わせて、再利用可能なスクリプトファイルを作成しましょう。

4.9.1 .ps1ファイルの作成

PowerShellスクリプトは .ps1 という拡張子のファイルに保存します。

まず、スクリプトを保存するフォルダを作成します。

[実行環境: PowerShell 7.4 (管理者)]

# スクリプト用フォルダを作成
New-Item -Path C:\Scripts -ItemType Directory -Force

次に、簡単なスクリプトファイルを作成します。

# スクリプトファイルを作成
$scriptContent = @'
# Hello-World.ps1
# 簡単な挨拶スクリプト

param (
    [string]$Name = "World"
)

Write-Host "Hello, $Name!" -ForegroundColor Cyan
Write-Host "現在の日時: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
'@

Set-Content -Path "C:\Scripts\Hello-World.ps1" -Value $scriptContent

4.9.2 スクリプトの実行方法

スクリプトを実行するにはいくつかの方法があります。

[実行環境: PowerShell 7.4 (管理者)]

# 方法1: フルパスで実行
C:\Scripts\Hello-World.ps1

# 方法2: 相対パスで実行(カレントディレクトリがC:\Scriptsの場合)
Set-Location C:\Scripts
.\Hello-World.ps1

# 方法3: パラメータを指定して実行
C:\Scripts\Hello-World.ps1 -Name "Administrator"

実行結果の例:

Hello, Administrator!
現在の日時: 2025-01-20 11:30:45

4.9.3 コメントの書き方

コードを読みやすくするために、適切なコメントを記述しましょう。

# 単一行コメント
# これは単一行のコメントです

<#
複数行コメント
これは複数行に
わたるコメントです
#>

# 関数やスクリプトの説明にはヘルプコメントを使用
<#
.SYNOPSIS
    サービスの状態を確認するスクリプト

.DESCRIPTION
    指定されたサービスの状態を確認し、結果を表示します。

.PARAMETER ServiceName
    確認するサービスの名前

.EXAMPLE
    .\Check-Service.ps1 -ServiceName "W32Time"
    W32Timeサービスの状態を確認します
#>

4.9.4 実践的なスクリプト例

サービス状態レポートを作成するスクリプトを作成しましょう。

[ファイル: C:\Scripts\Get-ServiceReport.ps1]

<#
.SYNOPSIS
    重要なサービスの状態レポートを作成します

.DESCRIPTION
    指定されたサービスの状態を確認し、レポートを出力します。

.PARAMETER Services
    確認するサービス名の配列

.PARAMETER OutputPath
    レポートの出力先パス(省略時は画面に表示)

.EXAMPLE
    .\Get-ServiceReport.ps1
    デフォルトのサービスリストでレポートを表示
#>

param (
    [string[]]$Services = @("W32Time", "Spooler", "WinRM", "EventLog", "Dnscache"),
    [string]$OutputPath
)

# レポートのヘッダー
$report = @()
$report += "=================================="
$report += "サービス状態レポート"
$report += "作成日時: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
$report += "=================================="
$report += ""

# 各サービスの状態を確認
foreach ($serviceName in $Services) {
    $service = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
    
    if ($null -eq $service) {
        $report += "[不明] $serviceName - サービスが見つかりません"
    }
    elseif ($service.Status -eq "Running") {
        $report += "[正常] $serviceName - 実行中"
    }
    else {
        $report += "[注意] $serviceName - $($service.Status)"
    }
}

$report += ""
$report += "=================================="

# 出力
if ($OutputPath) {
    $report | Set-Content -Path $OutputPath -Encoding UTF8
    Write-Host "レポートを保存しました: $OutputPath" -ForegroundColor Green
}
else {
    $report | ForEach-Object { Write-Host $_ }
}

このスクリプトを作成して実行します。

[実行環境: PowerShell 7.4 (管理者)]

# スクリプトファイルを作成(上記の内容をコピー)
# 実行
C:\Scripts\Get-ServiceReport.ps1

実行結果の例:

==================================
サービス状態レポート
作成日時: 2025-01-20 11:45:30
==================================

[正常] W32Time - 実行中
[正常] Spooler - 実行中
[正常] WinRM - 実行中
[正常] EventLog - 実行中
[正常] Dnscache - 実行中

==================================

4.10 エラーハンドリング基礎

スクリプトの信頼性を高めるには、エラーを適切に処理することが重要です。

4.10.1 エラーの種類

PowerShellのエラーには2種類あります。

種類 説明
終了エラー(Terminating Error) 処理を中断するエラー コマンドレットの致命的エラー、throw
非終了エラー(Non-Terminating Error) エラーを表示して処理を継続 ファイルが見つからない、アクセス拒否

4.10.2 -ErrorActionパラメータ

コマンドレットのエラー動作を制御するには、-ErrorAction パラメータを使用します。

動作
Continue エラーを表示して処理を継続(デフォルト)
Stop エラーを終了エラーとして処理を中断
SilentlyContinue エラーを表示せずに処理を継続
Ignore エラーを完全に無視($Errorにも記録されない)

[実行環境: PowerShell 7.4 (管理者)]

# エラーを無視して処理を継続
$service = Get-Service -Name "存在しないサービス" -ErrorAction SilentlyContinue

if ($null -eq $service) {
    Write-Host "サービスが見つかりませんでした。"
}

4.10.3 try-catch-finally構文

エラーをキャッチして適切に処理するには、try-catch-finally 構文を使用します。

[実行環境: PowerShell 7.4 (管理者)]

# 基本的なtry-catch
try {
    # エラーが発生する可能性のある処理
    $service = Get-Service -Name "存在しないサービス" -ErrorAction Stop
    Write-Host "サービス状態: $($service.Status)"
}
catch {
    # エラー発生時の処理
    Write-Host "エラーが発生しました: $($_.Exception.Message)" -ForegroundColor Red
}
finally {
    # 必ず実行される処理(省略可能)
    Write-Host "処理を完了しました。"
}

実行結果の例:

エラーが発生しました: Cannot find any service with service name '存在しないサービス'.
処理を完了しました。

特定の例外をキャッチ

# 特定の例外タイプをキャッチ
try {
    $content = Get-Content -Path "C:\存在しないファイル.txt" -ErrorAction Stop
}
catch [System.Management.Automation.ItemNotFoundException] {
    Write-Host "ファイルが見つかりません。" -ForegroundColor Yellow
}
catch [System.UnauthorizedAccessException] {
    Write-Host "アクセスが拒否されました。" -ForegroundColor Red
}
catch {
    Write-Host "予期しないエラー: $($_.Exception.Message)" -ForegroundColor Red
}

4.10.4 $Error変数

$Error は、セッション中に発生したエラーを格納する自動変数です。

[実行環境: PowerShell 7.4 (管理者)]

# 直近のエラーを確認
$Error[0]

# エラーの詳細を確認
$Error[0] | Format-List -Force

# エラーをクリア
$Error.Clear()

4.10.5 実践的なエラーハンドリング例

サービス管理スクリプトにエラーハンドリングを追加します。

[ファイル: C:\Scripts\Check-ServiceStatus.ps1]

<#
.SYNOPSIS
    サービスの状態を確認し、必要に応じて起動します
#>

param (
    [Parameter(Mandatory)]
    [string]$ServiceName
)

function Test-AndStartService {
    param (
        [string]$Name
    )
    
    try {
        # サービスの取得を試行
        $service = Get-Service -Name $Name -ErrorAction Stop
        
        Write-Host "サービス '$Name' を確認しました。" -ForegroundColor Cyan
        Write-Host "現在の状態: $($service.Status)"
        
        # サービスが停止している場合は起動を試行
        if ($service.Status -eq "Stopped") {
            Write-Host "サービスを起動しています..." -ForegroundColor Yellow
            
            try {
                Start-Service -Name $Name -ErrorAction Stop
                Write-Host "サービスを起動しました。" -ForegroundColor Green
            }
            catch {
                Write-Host "サービスの起動に失敗しました: $($_.Exception.Message)" -ForegroundColor Red
                return $false
            }
        }
        
        return $true
    }
    catch [Microsoft.PowerShell.Commands.ServiceCommandException] {
        Write-Host "サービス '$Name' が見つかりません。" -ForegroundColor Red
        return $false
    }
    catch {
        Write-Host "予期しないエラーが発生しました: $($_.Exception.Message)" -ForegroundColor Red
        return $false
    }
}

# メイン処理
$result = Test-AndStartService -Name $ServiceName

if ($result) {
    Write-Host "`n処理が正常に完了しました。" -ForegroundColor Green
}
else {
    Write-Host "`n処理中にエラーが発生しました。" -ForegroundColor Red
    exit 1
}

4.11 まとめ

第4回では、以下の内容を学びました。

  • 変数の基礎
    • $ 記号で変数を定義、GetType() で型を確認
    • 主要なデータ型:String、Int32、Double、Boolean、Array、Hashtable
    • 特殊変数:$null$true$false$_$Error
  • 文字列操作
    • ダブルクォートで変数展開、シングルクォートでリテラル
    • ヒアストリング(@" "@)で複数行文字列
    • 文字列メソッド:ToUpper()Split()Replace()Trim() など
  • 配列とハッシュテーブル
    • 配列:@() で作成、インデックスでアクセス
    • ハッシュテーブル:@{} で作成、キーと値のペア
  • 条件分岐
    • 比較演算子:-eq-ne-gt-lt-like-match
    • if-elseif-else 文、switch
    • 三項演算子(PowerShell 7以降):条件 ? 真 : 偽
  • ループ処理
    • foreach 文:コレクションの反復処理
    • for 文:カウンタベースの繰り返し
    • whiledo-while 文:条件ベースの繰り返し
    • ForEach-Object:パイプラインでの使用、-Parallel で並列処理
    • breakcontinue でループ制御
  • 関数の定義
    • function キーワードと param() ブロック
    • [Parameter(Mandatory)] で必須パラメータ
    • [ValidateSet()] で値を制限
    • スコープ:ローカル変数とグローバル変数
  • スクリプトファイルの作成
    • .ps1 ファイルの作成と実行
    • コメント:#(単一行)、<# #>(複数行)
  • エラーハンドリング
    • 終了エラーと非終了エラー
    • -ErrorAction パラメータ:Stop、SilentlyContinue など
    • try-catch-finally 構文
    • $Error 変数でエラー情報を確認

これらのスクリプティング技術は、今後のサーバー管理の自動化に直接活用できます。

4.12 次回予告

第5回では「Windowsサービスの管理 ― サーバーの心臓部を理解する」と題して、サービスの概念と役割、状態確認・起動・停止の方法、スタートアップの種類の設定、そしてサービス監視スクリプトの作成を学びます。今回学んだスクリプティング技術を活用して、実践的なサービス管理を行いましょう。

4.13 参考リンク

Windows Server