Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

PowerShell 解説書

PowerShell 7.x(クロスプラットフォーム)を中心としたシェル環境、オブジェクト指向パイプライン、スクリプト開発、システム管理・自動化の基礎から実践までを体系的に解説する手引きです。

章構成

入門編:PowerShellの概要と環境構築

PowerShell の基本概念、従来のコマンド環境との違い、PowerShell 7 の導入手順、およびコマンド探索に不可欠なヘルプ機能について解説します。

PowerShellとは

PowerShell は、Microsoft が開発したコマンドラインシェルおよびスクリプト言語です。システム管理、クラウド運用の自動化、日常的な定型作業の効率化を目的として広く利用されています。

従来のコマンドプロンプト(cmd.exe)や Linux の Bash などのシェルは、コマンド間のデータの受け渡しをすべて単純な「文字列(テキスト)」として行います。そのため、目的のデータを取り出すには文字列の切り出しや正規表現による複雑な加工が必要でした。

PowerShell の最大の特徴は、データを文字列ではなく「オブジェクト(属性や振る舞いを持つ構造化データ)」として扱う点にあります。この仕組みにより、出力結果の解析や加工を直感的かつ安全に行うことができます。

Windows PowerShell 5.1 と PowerShell 7.x

PowerShell には、Windows に標準搭載されている「Windows PowerShell 5.1」と、最新のオープンソース版である「PowerShell 7.x」の2系統が存在します。

項目Windows PowerShell 5.1PowerShell 7.x
実行ファイル名powershell.exepwsh.exe(または pwsh)
基盤フレームワーク.NET Framework(Windows専用).NET(クロスプラットフォーム)
対応OSWindows のみWindows, macOS, Linux
開発状態保守運用(機能追加終了)活発な新機能追加・性能改善中
並行処理機能なし(バックグラウンドジョブのみ)ForEach-Object -Parallel 対応

現代のシステム開発やクロスプラットフォーム環境での自動化では、PowerShell 7.x の利用が標準です。

インストールと起動

各 OS における PowerShell 7 の導入方法と起動手順を説明します。

» Windows への導入

Windows では、パッケージマネージャー(winget)を使用して簡単に導入できます。管理者権限または一般ユーザー権限のターミナルで次のコマンドを実行します。

winget install --id Microsoft.PowerShell --source winget

インストール完了後、ターミナルで pwsh と入力して起動します。

» macOS への導入

macOS では、Homebrew を使用してインストールします。

brew install --cask powershell

» Linux への導入

Ubuntu や Debian などのディストリビューションでは、Microsoft リポジトリを登録するか、パッケージマネージャー経由でインストールします。

sudo apt-get update
sudo apt-get install -y powershell

実行ポリシー(ExecutionPolicy)の確認と設定

PowerShell には、未検証のスクリプトが誤って実行される事故を防ぐための「実行ポリシー」という安全機構が用意されています。これはセキュリティの境界線ではなく、ユーザーの操作ミスを防止するための保護機構です。

現在の実行ポリシーを確認するには Get-ExecutionPolicy を実行します。

Get-ExecutionPolicy -List

既定ではスクリプト実行が制限されている場合があります。自分で作成したスクリプトやインターネットからダウンロードした署名付きスクリプトを実行可能にするには、現在のユーザーのスコープに対してポリシーを RemoteSigned に変更します。

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

探索とヘルプの3大コマンドレット

PowerShell には、コマンドの仕様や使い方を調べるための3つの基本コマンドレットが用意されています。

» Get-Command(コマンドの検索)

利用可能なコマンドレット、関数、エイリアスを検索します。名詞や動詞にワイルドカード(*)を指定して探すことができます。

# サービス関連のコマンドを一覧表示する
Get-Command *-Service

# Process という名詞を持つコマンドを検索する
Get-Command -Noun Process

» Get-Help(使い方の確認)

指定したコマンドレットの使い方、構文、パラメータ一覧、使用例を確認します。

# 基本的な使い方を表示する
Get-Help Get-Process

# 実用的なコード例を表示する
Get-Help Get-Process -Examples

# 最新のヘルプコンテンツをインターネットからダウンロードして更新する
Update-Help

» Get-Member(オブジェクトの構造確認)

コマンドの出力結果がどのようなプロパティ(値)やメソッド(操作)を持っているかを調査します。PowerShell のオブジェクト指向を理解する上で最も重要なコマンドレットです。

# プロセスオブジェクトが持つプロパティとメソッドを調べる
Get-Process | Get-Member

入門編:コマンドレットと基本文法

PowerShell の中核となるコマンドレットの命名規則、パラメータの扱い方、エイリアス、および文字列やコメントなどの基本文法を解説します。

コマンドレットの命名規則(動詞-名詞)

PowerShell のコマンドは「コマンドレット(Cmdlet)」と呼ばれ、すべて 動詞-名詞 の形式で統一されています。

動詞は操作の種類を示し、名詞は操作対象を示します。名詞部分は単数形を使用するのが原則です。

  • Get-Process: プロセスを取得する
  • Start-Service: サービスを開始する
  • Stop-Service: サービスを停止する
  • New-Item: 新しいファイルやフォルダを作成する
  • Remove-Item: ファイルやフォルダを削除する

PowerShell で使用できる標準的な動詞は定められており、Get-Verb コマンドレットで一覧を確認できます。勝手な動詞を使わずに承認された動詞を使用することで、未知のコマンドであっても直感的に用途を予測できます。

パラメータと引数の指定方法

コマンドレットに与えるパラメータ(引数)には、いくつかの指定方式が存在します。

» 名前付きパラメータ

ハイフン - に続けてパラメータ名を指定し、その後に値を記述します。パラメータの順序は自由です。

Get-ChildItem -Path "C:\workspace" -Filter "*.txt"

» 位置パラメータ

パラメータ名を省略し、定義された順番通りに値を直接渡す方式です。例えば Get-ChildItem の第1引数は -Path であるため、パラメータ名を省略できます。

Get-ChildItem "C:\workspace"

» スイッチパラメータ

値を必要とせず、指定するだけでオンになるフラグのようなパラメータです。

# -Recurse(再帰的に検索)と -Force(隠しファイルを含める)を指定
Get-ChildItem -Path "C:\workspace" -Recurse -Force

» WhatIf と Confirm

システムに変更を加えるコマンドレットの多くは、安全にテストするための -WhatIf パラメータと、実行前に確認を求める -Confirm パラメータを備えています。

# 実際に削除せず、何が削除されるかシミュレーションする
Remove-Item -Path "./temp/*" -Recurse -WhatIf

エイリアス(別名)の役割

PowerShell には、Unix シェルやコマンドプロンプトの利用者が違和感なく操作できるように、短い別名(エイリアス)が多数登録されています。

エイリアス正式なコマンドレット名主な役割
ls, dirGet-ChildItemファイルやフォルダの一覧表示
cp, copyCopy-Itemファイルやフォルダのコピー
rm, delRemove-Itemファイルやフォルダの削除
cat, typeGet-Contentファイル内容の読み込み
where, ?Where-Objectデータの条件絞り込み
selectSelect-Objectプロパティの選択・抽出

日常の対話的なターミナル操作ではエイリアスを使うと素早く入力できます。一方、保存するスクリプトファイル(.ps1)では、可読性と移植性を高めるために必ず正式なコマンドレット名を記述することが推奨されます。

文字列とクォートの使い分け

PowerShell における文字列の表現には、シングルクォート(')とダブルクォート(")の2種類があります。

» シングルクォート(リテラル文字列)

囲まれた文字列をそのまま文字として解釈します。変数や特殊記号は展開されません。

$name = "Taro"
Write-Output 'Hello, $name'
# 出力結果: Hello, $name

» ダブルクォート(展開文字列)

文字列内の変数をその値に自動展開します。プロパティや式を展開したい場合は $() というサブ式構文を使用します。

$name = "Taro"
$user = [PSCustomObject]@{ Name = "Hanako"; Age = 20 }

Write-Output "Hello, $name"
# 出力結果: Hello, Taro

Write-Output "Name: $($user.Name), Age: $($user.Age)"
# 出力結果: Name: Hanako, Age: 20

エスケープシーケンスとコメント

特殊な制御文字の入力やコード内の注釈記述について説明します。

» エスケープ文字(バッククォート)

PowerShell のエスケープ文字は円記号(\)ではなく、バッククォート(`)を使用します。

# 改行(`n)とタブ(`t)の挿入
Write-Output "Line 1`n`tLine 2 indented"

# 変数展開の無効化(ドル記号を文字として出力)
Write-Output "Value is `$name"

» コメントの記述

単一行のコメントには # を使用し、複数行にまたがるコメントには <# ... #> を使用します。

# これは単一行コメントです
$port = 8080

<#
これは複数行コメントです。
関数の概要や注意点を詳しく
記録するために利用します。
#>

入門編:オブジェクト指向パイプラインの基礎

テキストではなく構造化オブジェクトをそのまま次のコマンドへ受け渡す PowerShell 固有のパイプラインの仕組みと、主要なデータ処理コマンドレットを解説します。

オブジェクト指向パイプラインとは

パイプライン記号(|)を使用すると、左側のコマンドの実行結果を右側のコマンドへの入力として渡すことができます。

Unix 系シェルではパイプラインを通じて流れるデータは単なる「文字列(バイトストリーム)」です。そのため、特定の項目を取得するには grep や awk、sed などの外部ツールで文字列を解析する必要がありました。

PowerShell のパイプラインを流れるのは文字列ではなく、型情報とプロパティ(属性)を持った「.NET オブジェクト」です。文字列の解析処理を書く必要がなく、プロパティ名を指定するだけで安全にデータを取り出せます。

Get-Member によるオブジェクトの解析

パイプラインを流れるオブジェクトがどのような型であり、どのような情報(プロパティ)や操作(メソッド)を持っているかを調べるには Get-Member を利用します。

Get-Service | Get-Member

このコマンドを実行すると、出力されるオブジェクトの型(System.ServiceProcess.ServiceController など)や、利用可能なプロパティ一覧(Name、Status、DisplayName など)が確認できます。

データの絞り込み(Where-Object)

Where-Object コマンドレットは、パイプラインから渡されたオブジェクトの中から、指定した条件に合致するものだけを抽出します。

» スクリプトブロック構文

波括弧 {} の中に条件式を記述します。パイプラインを流れてくる各オブジェクトは $_(または $PSItem)という特殊変数で参照します。

# 実行中のサービスのみを抽出する
Get-Service | Where-Object { $_.Status -eq "Running" }

» 比較演算子

PowerShell の比較演算子は記号(< や >)ではなく、英字の短縮形を使用します。

演算子意味使用例
-eq等しい(Equal)$_.Status -eq "Running"
-ne等しくない(Not Equal)$_.Id -ne 0
-gtより大きい(Greater Than)$_.CPU -gt 10
-ge以上(Greater or Equal)$_.Length -ge 1MB
-ltより小さい(Less Than)$_.Count -lt 5
-le以下(Less or Equal)$_.Count -le 10
-likeワイルドカード一致$_.Name -like "Power*"
-match正規表現一致$_.Version -match "^7\."

» 簡略構文

単純な比較の場合、波括弧や $_ を省略して直感的に記述できます。

Get-Service | Where-Object Status -eq "Running"

プロパティの抽出と計算(Select-Object)

Select-Object は、オブジェクトから特定のプロパティを取り出したり、件数を制限したりする際に使用します。

» 特定のプロパティの抽出

不要な情報を省き、必要な列だけを画面に表示したり次の処理に渡したりできます。

Get-Process | Select-Object -Property Name, Id, CPU

» 件数の制御

-First や -Last パラメータを使うと、先頭や末尾の指定件数のみを取得できます。

# 先頭の5件のみ取得する
Get-Process | Select-Object -First 5

» 計算プロパティ(カスタム列の作成)

ハッシュテーブル構文 @{ Name = "..."; Expression = { ... } } を用いて、既存の値を加工した新しい列を動的に定義できます。

# メモリ使用量(バイト)をメガバイト単位(MB)に換算して表示する
Get-Process | Select-Object -Property Name, @{
    Name = "MemoryMB"
    Expression = { [math]::Round($_.WorkingSet64 / 1MB, 2) }
}

データの並べ替えとグループ化

取得したオブジェクトの並べ替えや集計を行うコマンドレットについて説明します。

» Sort-Object(並べ替え)

指定したプロパティを基準にオブジェクトを昇順または降順で整列させます。

# CPU使用率の高い順(降順)に上位10プロセスを表示する
Get-Process | Sort-Object -Property CPU -Descending | Select-Object -First 10

» Group-Object(グループ化)

共通の値を持つオブジェクトごとにグループ化し、グループごとの件数や内訳を集計します。

# サービスを稼働状態(Status)ごとにグループ化して集計する
Get-Service | Group-Object -Property Status

実践編:変数・データ型・コレクション

PowerShell における変数の宣言とスコープ、基本的なデータ型と型変換、配列およびハッシュテーブル(連想配列)の操作方法を解説します。

変数の定義とスコープ

PowerShell の変数名は先頭にドル記号($)を付与して定義します。代入演算子(=)を用いて値を格納します。

$serverName = "web01.internal"
$maxRetries = 3
$isEnabled = $true

» 変数スコープ

変数にはアクセス可能な有効範囲(スコープ)が存在します。スコープ修飾子を明示することで有効範囲を指定できます。

  • $local:: 現在のブロックまたは関数内でのみ有効(指定なしのデフォルト)
  • $script:: 実行中のスクリプトファイル全体で有効
  • $global:: セッション全体で有効
  • $env:: オペレーティングシステムの環境変数を参照・更新
# 環境変数へのアクセス
Write-Output "User profile path: $env:USERPROFILE"

# 一時的な環境変数の設定
$env:NODE_ENV = "production"

基本データ型と型キャスト

PowerShell は .NET の豊富な型システムを直接利用します。通常は自動で型が判別されますが、明示的に型を指定(型キャスト)することも可能です。

型名説明例
[string]文字列"PowerShell"
[int]32ビット符号付き整数42
[double]倍精度浮動小数点数3.14159
[bool]真偽値($true / $false)$true
[datetime]日付・時刻オブジェクト[datetime]"2026-09-27"

» 型キャストの例

角括弧 [] を変数の前につけることで、文字列を数値や日付型に変換できます。

# 文字列を数値に変換
$num = [int]"128"

# 文字列を日付オブジェクトに変換
$date = [datetime]"2026-09-27 10:00:00"
Write-Output "Year: $($date.Year), Day of Week: $($date.DayOfWeek)"

配列(Array)の作成と操作

複数の値をまとめて管理する配列の基本的な使い方を説明します。

» 配列の作成

要素をカンマで区切るか、配列部分式 @(...) を使用して作成します。

# カンマ区切りによる配列
$fruits = "Apple", "Banana", "Cherry"

# 空の配列
$emptyArray = @()

# 連続した数値の範囲演算子
$numbers = 1..10

» インデックス参照

要素へのアクセスには角括弧インデックスを使用します。0から始まり、-1 は末尾の要素を表します。

Write-Output $fruits[0]   # Apple
Write-Output $fruits[-1]  # Cherry

» 要素の追加と List 型

+= 演算子で配列に要素を追加できますが、内部的には配列全体を新しく作り直すため、要素数が多い場合は処理速度が低下します。大量のデータを扱う場合は List[T] を利用します。

# 大量データを効率よく扱うジェネリックリスト
$list = [System.Collections.Generic.List[string]]::new()
$list.Add("Alpha")
$list.Add("Beta")
$list.Add("Gamma")

ハッシュテーブルとカスタムオブジェクト

キーと値のペアで管理するハッシュテーブル(連想配列)と、独自のプロパティを持つオブジェクトの作成方法です。

» ハッシュテーブル(Hashtable)

@{} 構文で定義し、キーと値をイコール記号で結びます。

$config = @{
    HostName = "192.168.1.10"
    Port     = 8080
    Protocol = "HTTPS"
}

# 値の参照と追加
Write-Output $config["HostName"]
$config["Timeout"] = 30

» カスタムオブジェクト(PSCustomObject)

ハッシュテーブルの先頭に [PSCustomObject] を付与すると、プロパティを持った構造化オブジェクトを作成できます。

$record = [PSCustomObject]@{
    Id     = 101
    Name   = "Web-Server-01"
    Active = $true
}

# プロパティとしてアクセス
Write-Output "$($record.Name) is active: $($record.Active)"

# パイプラインコマンド(Export-Csv 等)にそのまま流すことが可能
$record | Select-Object -Property Id, Name

実践編:制御構文と関数・スクリプト作成

条件分岐やループ処理といった制御構文、保守性の高い高度な関数(Advanced Function)の定義、およびスクリプトファイル(.ps1)の作成と実行方法を解説します。

条件分岐(if と switch)

プログラムの処理を条件に応じて分岐させる構文について説明します。

» if / elseif / else

条件式を丸括弧 () で囲み、条件を満たしたときに実行する処理を波括弧 {} 内に記述します。

$status = 200

if ($status -eq 200) {
    Write-Output "通信成功 (OK)"
} elseif ($status -eq 404) {
    Write-Output "対象が見つかりません (Not Found)"
} else {
    Write-Output "予期しないステータス: $status"
}

» switch

複数の値に応じて分岐させたい場合や、パターンマッチングを行いたい場合は switch を使用します。

$role = "admin"

switch ($role) {
    "admin" {
        Write-Output "管理者権限です"
        break
    }
    "editor" {
        Write-Output "編集者権限です"
        break
    }
    default {
        Write-Output "一般ユーザー権限です"
    }
}

繰り返し構文(foreach と ForEach-Object)

コレクションの要素を順番に処理するループ構文です。PowerShell では言語構文の foreach と、パイプラインコマンドレットの ForEach-Object の使い分けが重要です。

» foreach ステートメント

メモリ上に読み込まれた配列を高速に反復処理します。

$services = "wuauserv", "bits", "spooler"

foreach ($s in $services) {
    Write-Output "Target service: $s"
}

» ForEach-Object コマンドレット

パイプラインから1件ずつデータを受け取ってストリーミング処理します。全件をメモリに載せる必要がないため、巨大なデータやログを処理する際にメモリ消費を抑えられます。

Get-ChildItem -Path "./logs" -Filter "*.log" | ForEach-Object {
    Write-Output "Log file: $($_.FullName), Size: $($_.Length) bytes"
}

関数の定義と高度な関数(CmdletBinding)

再利用可能な処理を関数としてまとめる方法です。

» 基本的な関数の定義

function Get-Greeting {
    param (
        [string]$Name = "Guest"
    )
    return "Hello, $Name!"
}

Get-Greeting -Name "Alice"

» 高度な関数(Advanced Functions)

先頭に [CmdletBinding()] 属性を付与することで、自作関数が標準のコマンドレットと同等の機能(-Verbose, -ErrorAction 等の共通パラメータ対応)を持つようになります。

function Backup-Configuration {
    [CmdletBinding(SupportsShouldProcess = $true)]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$SourcePath,

        [Parameter(Mandatory = $true)]
        [string]$DestinationPath
    )

    process {
        if ($PSCmdlet.ShouldProcess($SourcePath, "Backup to $DestinationPath")) {
            Copy-Item -Path $SourcePath -Destination $DestinationPath -Force
            Write-Verbose "Backup completed successfully: $SourcePath"
        }
    }
}

SupportsShouldProcess = $true を宣言することで、自動的に -WhatIf や -Confirm パラメータが有効化されます。

スクリプトファイル(.ps1)の作成と実行

一連の処理を .ps1 拡張子のファイルとして保存することで、バッチ処理や自動化スクリプトとして実行できます。

» スクリプトの定義例(deploy.ps1)

# スクリプト全体で受け取る引数を定義
param (
    [Parameter(Mandatory = $true)]
    [string]$Environment,

    [int]$Port = 8080
)

Write-Output "Starting deployment to $Environment on port $Port..."

if (-not (Test-Path -Path "./build")) {
    Write-Error "Build directory does not exist."
    exit 1
}

Write-Output "Deployment succeeded."
exit 0

» スクリプトの実行方法

カレントディレクトリのスクリプトを実行する際は、安全のため相対パス(./)を明示して呼び出します。

./deploy.ps1 -Environment "Production" -Port 443

実践編:ファイル操作とテキスト処理

プロバイダモデルを通じたファイルシステムの基本操作、ファイルの読み書き、正規表現を用いたテキスト検索、および JSON や CSV の変換処理を解説します。

プロバイダモデルとファイルシステム操作

PowerShell では「プロバイダ」という仕組みにより、通常のファイルシステムだけでなく、レジストリや環境変数もドライブ(仮想ドライブ)のように同じコマンドで操作できます。

Get-PSDrive を実行すると、利用可能なドライブ一覧(C:, Env:, Variable:, HKCU: 等)が表示されます。

» ファイル・ディレクトリの主要コマンド

操作コマンドレット例
存在確認Test-PathTest-Path -Path "./config.json"
新規作成New-ItemNew-Item -ItemType Directory -Path "./logs"
一覧取得Get-ChildItemGet-ChildItem -Path "./src" -Recurse
コピーCopy-ItemCopy-Item -Path "a.txt" -Destination "b.txt"
移動Move-ItemMove-Item -Path "old.txt" -Destination "./archive/"
削除Remove-ItemRemove-Item -Path "./temp" -Recurse -Force

» パスの安全な操作(Join-Path と Split-Path)

文字列の結合ではなく専用のコマンドレットを使うことで、OS の区切り文字(/ や \)の違いを気にせず安全にパスを扱えます。

# パスの結合
$targetFile = Join-Path -Path "C:\workspace" -ChildPath "data\result.txt"

# ファイル名や親ディレクトリの抽出
$parentDir = Split-Path -Path $targetFile -Parent
$fileName  = Split-Path -Path $targetFile -Leaf

ファイルの読み込みと書き込み

テキストファイルの効率的な読み書き方法です。

» ファイルの読み込み(Get-Content)

ファイルの内容を1行ずつの配列として読み込みます。

# 全体を読み込む
$lines = Get-Content -Path "./sample.txt"

# ログファイルの末尾10行をリアルタイム監視する(Unix の tail -f に相当)
Get-Content -Path "./access.log" -Tail 10 -Wait

» ファイルへの書き込み(Set-Content と Add-Content)

新規書き込み(上書き)には Set-Content、追記には Add-Content を使用します。PowerShell 7 では既定の文字コードが BOM なしの UTF-8(utf8NoBOM)です。

# 新規作成または上書き
Set-Content -Path "./output.txt" -Value "First line"

# 末尾に追記
Add-Content -Path "./output.txt" -Value "Second line"

テキスト検索と正規表現

テキストデータから目的のパターンを抽出する手法です。

» Select-String(テキスト検索)

Unix の grep コマンドに相当し、ファイル内やパイプライン入力から正規表現パターンを検索します。

# ログファイルから ERROR または WARN を含む行を検索
Select-String -Path "./logs/*.log" -Pattern "(ERROR|WARN)"

» -match 演算子と自動変数 $Matches

正規表現で一致判定を行い、キャプチャした文字列を $Matches 変数から取得します。

$line = "2026-09-27 15:30:00 [INFO] Task completed in 420ms"

if ($line -match "Task completed in (?<duration>\d+)ms") {
    $time = $Matches["duration"]
    Write-Output "Duration: $time ms"
}

構造化データ(JSON と CSV)の処理

Web API や設定ファイルで多用されるデータ形式の相互変換です。

» JSON の相互変換

ConvertFrom-Json は JSON 文字列をカスタムオブジェクトに変換し、ConvertTo-Json はオブジェクトを JSON 文字列にシリアライズします。

# JSON 文字列からオブジェクトへの変換
$jsonText = '{"name": "AppServer", "port": 8080}'
$obj = $jsonText | ConvertFrom-Json
Write-Output $obj.name

# オブジェクトから JSON 文字列への変換(階層の深さは -Depth で指定)
$jsonOutput = $obj | ConvertTo-Json -Depth 5

» CSV の相互変換

表形式データを手軽にインポート・エクスポートできます。

# CSV ファイルの読み込み
$servers = Import-Csv -Path "./servers.csv"

# オブジェクト一覧を CSV として保存
Get-Process | Select-Object -Property Id, Name, WorkingSet64 |
    Export-Csv -Path "./process_list.csv" -NoTypeInformation -Encoding utf8

実践編:エラー処理とデバッグ

PowerShell におけるエラーの種類、例外処理構文(try/catch)、エラー動作の制御、および効果的なロギングとデバッグ手法を解説します。

エラーの種類(終了エラーと非終了エラー)

PowerShell のエラーには大きく分けて2つの種類があります。

  • 非終了エラー(Non-terminating Error): コマンドの実行中に一部の処理が失敗しても、残りの処理を中断せずに継続するエラーです(例: 存在しないファイルを1つ開こうとした場合など)。

  • 終了エラー(Terminating Error): スクリプトの実行を即座に停止させる致命的なエラーや例外です。構文エラーや throw で意図的に発生させた例外が該当します。

ErrorAction による動作の制御

非終了エラーが発生した際の動作は、環境変数 $ErrorActionPreference や各コマンドレットの -ErrorAction パラメータで細かく制御できます。

設定値動作
Continueエラーメッセージを表示し、処理を続行(既定値)
Stopエラーメッセージを表示し、終了エラーとして処理を停止
SilentlyContinueエラーメッセージを表示せず、静かに処理を続行
Inquire処理を続行するかユーザーに対話式で確認

» スクリプト全体での安全対策

スクリプトファイルの先頭で $ErrorActionPreference = "Stop" を宣言すると、軽微なエラーであっても即座に停止し、意図しないデータ破損や誤動作を防ぐことができます。

# 未定義変数の参照を禁止
Set-StrictMode -Version Latest

# エラー発生時は即座に停止
$ErrorActionPreference = "Stop"

try / catch / finally による例外処理

終了エラーは try / catch / finally 構文で捕捉して安全にリカバリー処理を実行できます。

非終了エラーを捕捉したい場合は、コマンドレットに -ErrorAction Stop を付与して終了エラーに昇格させます。

try {
    # 存在しないパスを指定し、終了エラーに昇格させる
    Get-ChildItem -Path "Z:\non-existent-path" -ErrorAction Stop
} catch [System.Management.Automation.ItemNotFoundException] {
    Write-Warning "指定されたパスが見つかりませんでした: $($_.Exception.Message)"
} catch {
    # その他のすべての例外を捕捉
    Write-Error "予期しないエラーが発生しました: $_"
} finally {
    # 成功・失敗にかかわらず必ず実行される後処理
    Write-Output "リソースのクリーンアップ処理を完了しました。"
}

catch ブロック内では、発生したエラーオブジェクトが特殊変数 $_(または $PSItem)に格納されます。

出力ストリームとロギング

PowerShell には目的ごとに分離された複数の出力ストリームが用意されています。用途に応じて適切なコマンドレットを使い分けることが重要です。

コマンドレット出力先ストリーム主な役割
Write-Output成功ストリーム(1)パイプラインに渡すメインの出力
Write-Errorエラーストリーム(2)エラー情報の出力
Write-Warning警告ストリーム(3)利用者への注意喚起
Write-Verbose詳細ストリーム(4)処理の進捗や詳細記録(-Verbose 指定時に表示)
Write-Debugデバッグストリーム(5)開発者向けの調査情報(-Debug 指定時に表示)

画面表示専用の Write-Host はパイプラインやリダイレクトで捕捉できないため、自動化スクリプトやツール開発では避け、Write-Output や Write-Verbose を使用します。

デバッグコマンドレットの活用

スクリプトの動作検証を対話的に行うためのデバッグ機能です。

  • Set-PSBreakpoint: 特定のスクリプト行や変数の変更時に処理を一時停止(ブレークポイント)
  • Get-PSBreakpoint: 設定中のブレークポイント一覧を表示
  • Remove-PSBreakpoint: ブレークポイントを解除
# backup.ps1 の15行目にブレークポイントを設定
Set-PSBreakpoint -Script "./backup.ps1" -Line 15

応用編:モジュール管理とPowerShell Gallery

PowerShell の機能を拡張・共有するためのモジュールの仕組み、公式リポジトリからのパッケージ導入、および自作モジュールの設計と配備方法を解説します。

モジュールとは何か

モジュールとは、関連するコマンドレット、関数、変数、プロバイダをひとまとめにした再利用可能なパッケージです。

PowerShell には標準でOS管理やネットワーク制御などのモジュールが組み込まれているほか、世界中の開発者が公開した数万を超えるモジュールを追加して利用できます。

モジュールを配置する標準のディレクトリパスは、環境変数 $env:PSModulePath にセミコロン(Windows)またはコロン(Unix)区切りで定義されています。

# モジュール検索パスの確認
$env:PSModulePath -split [System.IO.Path]::PathSeparator

「PowerShell Gallery」は、Microsoft およびコミュニティが提供する公式のリポジトリ(パッケージカタログ)です。

» 従来の PowerShellGet による管理

# モジュールの検索
Find-Module -Name "PSScriptAnalyzer"

# 現在のユーザー環境にインストール
Install-Module -Name "PSScriptAnalyzer" -Scope CurrentUser -Force

# インストール済みモジュールの更新
Update-Module -Name "PSScriptAnalyzer"

» 最新の PSResourceGet(PowerShell 7 推奨)

PowerShell 7.4 以降では、より高速で軽量な Microsoft.PowerShell.PSResourceGet が標準採用されています。

# 高速なリソース検索とインストール
Find-PSResource -Name "Terminal-Icons"
Install-PSResource -Name "Terminal-Icons" -Scope CurrentUser

モジュールのインポートと一覧確認

モジュールの読み込み状態を確認・制御するコマンドレットです。

PowerShell 3.0 以降、モジュール内に含まれるコマンドを実行すると自動的にバックグラウンドでインポートされる「自動ロード(Autoloading)」が機能します。そのため、明示的なインポート処理を省略できるケースが一般的です。

# 現在のセッションに読み込まれているモジュール一覧
Get-Module

# システムにインストールされており読み込み可能な全モジュール
Get-Module -ListAvailable

# 明示的なモジュールの読み込みとアンロード
Import-Module -Name "PSScriptAnalyzer"
Remove-Module -Name "PSScriptAnalyzer"

独自スクリプトモジュールの作成

チーム内での共通処理や定型スクリプトを共有するための自作モジュール作成手順です。

» 1. スクリプトファイル(.psm1)の作成

モジュールの本文となる関数を定義し、公開したいコマンドのみを Export-ModuleMember で明示します。

# MyTools.psm1
function New-CustomLog {
    [CmdletBinding()]
    param([string]$Message)
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    Write-Output "[$timestamp] $Message"
}

# 外部に公開する関数を指定
Export-ModuleMember -Function New-CustomLog

» 2. マニフェストファイル(.psd1)の生成

バージョン番号、作成者、依存モジュールなどのメタデータを定義します。New-ModuleManifest を使用してテンプレートを自動生成できます。

New-ModuleManifest -Path "./MyTools.psd1" `
    -RootModule "MyTools.psm1" `
    -ModuleVersion "1.0.0" `
    -Author "DevTeam" `
    -Description "Internal automation toolset"

作成したフォルダ(MyTools)を $env:PSModulePath のいずれかの配下に配置することで、他のスクリプトから簡単に呼び出せるようになります。

応用編:システム管理・REST API連携と自動化

システム管理の基本となるプロセス・サービスの制御、Web API との通信、PowerShell 7 の強力な並行処理、およびスクリプトの自動実行手法を解説します。

プロセスとサービスの管理

実行中のプログラムやシステム常駐サービスの状態監視と制御を行います。

» プロセスの監視と終了

# メモリ使用量の多い上位5プロセスを抽出
Get-Process | Sort-Object -Property WorkingSet64 -Descending | Select-Object -First 5

# 特定の名前のプロセスを安全に停止
Stop-Process -Name "notepad" -Force -ErrorAction SilentlyContinue

» サービスの制御

# サービスの状態確認
Get-Service -Name "wuauserv"

# サービスの再起動
Restart-Service -Name "wuauserv"

REST API との連携

PowerShell には、Web API とやり取りするためのコマンドレットが標準で備わっています。

» Invoke-RestMethod(API からのデータ取得)

JSON や XML 形式のレスポンスを自動的に .NET オブジェクトへ変換して返します。

# GitHub API からリポジトリ情報を取得
$uri = "https://api.github.com/repos/powershell/powershell"
$repo = Invoke-RestMethod -Uri $uri -Method Get

Write-Output "Stars: $($repo.stargazers_count)"
Write-Output "Forks: $($repo.forks_count)"

» 認証ヘッダーと POST リクエスト

API トークンを用いた認証やデータの送信も容易に行えます。

$headers = @{
    Authorization = "Bearer your_token_here"
    "Content-Type" = "application/json"
}

$body = @{
    title = "Bug report"
    body  = "Discovered issue during build"
} | ConvertTo-Json

$response = Invoke-RestMethod -Uri "https://api.example.com/issues" `
    -Method Post `
    -Headers $headers `
    -Body $body

バックグラウンドジョブと並行処理

大量の処理を非同期または並列で実行することで、スクリプト全体の所要時間を大幅に短縮できます。

» PowerShell 7 の並行処理(ForEach-Object -Parallel)

PowerShell 7 から導入されたスレッドベースの並行処理機能です。従来のプロセスベースのジョブに比べて起動が極めて高速で、メモリ消費も抑えられます。

$urls = @(
    "https://www.google.com",
    "https://www.microsoft.com",
    "https://github.com"
)

# 最大3スレッドで同時にリクエストを送信
$urls | ForEach-Object -Parallel {
    $sw = [System.Diagnostics.Stopwatch]::StartNew()
    $res = Invoke-WebRequest -Uri $_ -Method Head -TimeoutSec 5
    $sw.Stop()
    [PSCustomObject]@{
        Url      = $_
        Status   = $res.StatusCode
        Duration = $sw.ElapsedMilliseconds
    }
} -ThrottleLimit 3

並行処理ブロックの中から外側の変数を参照する場合は、$using:変数名 というスコープ修飾子を使用します。

スクリプトの自動実行と無人運用

タスクスケジューラや CI/CD パイプラインでスクリプトを安全に自動実行するためのパラメータ設定です。

pwsh -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "./backup.ps1"
  • -NoProfile: ユーザープロファイル(起動時設定)の読み込みをスキップし、起動速度と再現性を向上
  • -NonInteractive: ユーザーに入力を求めるプロンプトを抑制し、ハングアップを防止
  • -ExecutionPolicy Bypass: 実行ポリシーによる制約を一時的にバイパス

応用編:セキュリティとベストプラクティス

パスワードや機密情報の安全な保護、コードの安全な実行、静的コード解析ツールを用いた品質担保、および保守性を高めるコーディング規約を解説します。

認証情報の安全な保護

スクリプト内にパスワードや API キーを平文(プレーンテキスト)で直接ハードコードすることは重大なセキュリティリスクとなります。

» PSCredential による対話的入力

パスワードをメモリ上で暗号化して保持する PSCredential オブジェクトを使用します。

# 対話的にユーザー名とパスワードを入力
$credential = Get-Credential

# 資格情報オブジェクトを用いた認証
Invoke-RestMethod -Uri "https://internal.service.local/api" -Credential $credential

» SecretManagement モジュールの活用

無人運用のスクリプトでは、公式の Microsoft.PowerShell.SecretManagement および Microsoft.PowerShell.SecretStore モジュールを用いて、OS のキーチェーンや暗号化ストアに機密情報を安全に保存・呼び出しを行います。

# 資格情報の保存
Set-Secret -Name "ProductionApiKey" -Secret "secret_value_12345"

# 資格情報の取得
$apiKey = Get-Secret -Name "ProductionApiKey" -AsPlainText

Invoke-Expression の危険性と安全な実行

文字列を PowerShell のコードとして評価・実行する Invoke-Expression(エイリアス iex)は、SQL インジェクションと同様の「コマンドインジェクション」を引き起こすリスクがあります。

外部からの入力値を含む文字列を直接実行することは避け、&(呼び出し演算子)やスクリプトブロックを使用します。

# 非推奨(危険):外部入力による任意のコマンド実行リスク
# Invoke-Expression "Get-Process -Name $userInput"

# 推奨:安全なコマンド実行
& "Get-Process" -Name $userInput

PSScriptAnalyzer による静的コード解析

PSScriptAnalyzer は、PowerShell スクリプトの品質、パフォーマンス、セキュリティ上の問題を自動検査する公式の静的コード解析ツールです。

# 現在のディレクトリ内の全スクリプトを検査
Invoke-ScriptAnalyzer -Path "." -Recurse

検査により、以下のような問題が事前に警告されます。

  • エイリアスの使用(ls, select 等の未展開記述)
  • 平文のパスワード定義
  • 承認されていない動詞の使用
  • グローバル変数の乱用

スクリプト作成のベストプラクティス

長期間にわたり保守しやすく、共同開発でトラブルの起きにくいスクリプトを作成するための基本方針です。

» 1. スクリプト内では正式名称を使用する

対話操作ではエイリアスが便利ですが、スクリプトファイル(.ps1)内では必ず完全なコマンドレット名とパラメータ名を記述します。これにより、第三者が読んだ際にも意図が明確になります。

» 2. クロスプラットフォームを意識したパス指定

Windows だけでなく Linux や macOS 上の PowerShell 7 でも動作するよう、パス区切り文字にはスラッシュ(/)を使用するか、Join-Path コマンドレットを使用します。

» 3. 承認された動詞に従う

自作の関数を命名する際は、Get-Verb で確認できる標準動詞(Get, Set, New, Remove, Test, Update 等)を採用します。一貫した命名規則により、利用者がコマンドを探しやすくなります。