PowerShellスクリプトのよくあるエラーと対処法まとめ

PowerShellのよくあるエラーと対処を解説する記事のアイキャッチ画像 Windows
PowerShellのよくあるエラーと対処

※本記事にはアフィリエイト広告(PR)を含みます。

PowerShellでスクリプトを書いていると、「自分の端末では動くのに別のサーバーやタスクスケジューラでは失敗する」「出力ファイルが文字化けする」「エラーが出ているはずなのに途中で止まらず、後工程で失敗に気づく」といったトラブルに繰り返し遭遇します。原因の多くは、実行ポリシーや文字コードの既定値、エラー処理の仕組みといったPowerShell特有の動作を理解していないことにあります。本記事では、Windows運用・自動化を担当するSE向けに、現場でよく踏む代表的なエラーと対処法を、実行ポリシー・文字化け・パスやクォートの書き方・エラーハンドリング・モジュール不足の5つの観点で整理します。

実行ポリシーで実行できない

最初によく当たるのが、.ps1を実行しようとして「スクリプトの実行が無効になっています」という趣旨のエラーで止まるケースです。全スコープが未設定(Undefined)の場合、有効な実行ポリシーはWindowsクライアントではRestricted(スクリプト実行不可)、Windows ServerではRemoteSignedになります。この既定差を知らないと、クライアントOSでの検証時に無用な混乱が生まれます。

PS C:\Scripts> .\sample.ps1
.\sample.ps1 : File C:\Scripts\sample.ps1 cannot be loaded because running
scripts is disabled on this system.

主な実行ポリシーは次のとおりです。

  • Restricted:スクリプトを一切実行しない(既定値)
  • RemoteSigned:自分の端末で作成したスクリプトはそのまま実行できるが、ダウンロードしたスクリプトは信頼された発行者の署名が必要
  • AllSigned:自作スクリプトも含めてすべて署名が必要
  • Bypass:何も制限せず警告も出さない(アプリ組み込みなど限定用途向け)

スコープの使い分け

変更にはSet-ExecutionPolicyを使いますが、対象スコープの理解が欠かせません。既定のLocalMachineスコープ(端末全体)の変更には管理者権限が必要です。CurrentUserスコープなら管理者権限なしで自分のユーザーだけに適用でき、共有端末での検証に向いています。Processスコープはそのセッション限りの一時適用です。

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

グループポリシーで強制されている環境(MachinePolicy/UserPolicy)では、個別に変更しても上書きされます。まずはGet-ExecutionPolicy -Listで各スコープの値を確認しましょう。

ダウンロードしたスクリプトがブロックされる場合

外部から取得したファイルには「インターネットゾーン」のマークが付くことがあり、RemoteSignedでは署名なしだとブロックされます。中身を確認して安全と判断できるなら、ポリシーを緩めるのではなくUnblock-Fileでマークを外す方法もあります。

Unblock-File -Path C:\Scripts\sample.ps1

文字化け・文字コードの罠

ログやCSV出力の文字化け、スクリプト中の日本語コメントが実行時に壊れるのも定番です。原因の多くは、Windows PowerShell 5.1とPowerShell 7(6以降)で既定の文字コードが違うことを知らずに環境を混在させることにあります。

出力ファイルの既定エンコーディングが違う

5.1では、Out-Fileやリダイレクト演算子(>、>>)の既定はUTF-16LE(Unicode)です。一方Set-Content/Add-Contentの既定は実行環境のANSIコードページ(日本語環境では通常Shift-JIS系)で、コマンドによって既定が揃っていません。さらに-Encoding UTF8を明示すると、5.1ではBOM付きUTF-8になります。

PowerShell 7ではOut-File・Set-Content・リダイレクト演算子など出力系コマンドの既定がBOMなしUTF-8(utf8NoBOM)に統一されています。5.1の感覚のまま「省略してもUTF-8になる」と思っていると、BOMの有無で後続処理がこけることがあるため、エンコーディングは省略せず明示するのが安全です。

Get-Content C:\Scripts\input.csv | Out-File -FilePath C:\Scripts\output.csv -Encoding utf8

スクリプトファイル自体が文字化けする

5.1はBOMなしのファイルを読み込む際にシステムのANSIコードページとして解釈しようとするため、日本語を含むスクリプトをBOMなしUTF-8で保存すると、5.1環境ではコメントや文字列が文字化けすることがあります。5.1中心の環境では保存形式を「BOM付きUTF-8」にしておくのが無難です。PowerShell 7ではBOMなしUTF-8でも正しく解釈されます。

パス・クォート・変数展開の書き方ミス

シングルクォート(‘…’)はリテラル文字列として扱われ、変数展開は行われません。ダブルクォート(“…”)は内部の変数が値に展開されます。これを意識しないと、変数名がそのまま文字として出力される、というミスにつながります。

$name = "server01"
Write-Output 'Hello $name'   # そのまま Hello $name
Write-Output "Hello $name"   # Hello server01 と展開

ダブルクォート内でドル記号を出力したい場合は、エスケープ文字のバッククォート(`)を使い`$と書きます。パスにスペースが含まれる場合は全体をクォートで囲み、変数化したパスを実行する際は呼び出し演算子&を使います。

$exe = "C:\Program Files\Sample App\tool.exe"
& $exe -Mode Silent

&を付けずに$exeだけ書くと文字列としか解釈されず、コマンドとして実行されません。パス生成はJoin-Path、スクリプト自身の場所は$PSScriptRootを基準にすると、タスクスケジューラなど想定と異なるカレントディレクトリでのトラブルを防げます。

エラーが握りつぶされて後工程で発覚する

「エラーなく終わったはずが、後で確認したら失敗していた」というのも定番です。多くの場合、既定のエラー処理を理解せずtry/catchを書いていることが原因です。

既定はContinue、try/catchは終了エラーしか拾わない

$ErrorActionPreferenceの既定値はContinueで、エラーを表示しつつ処理を継続します。多くのコマンドレットはエラー発生時も「非終了エラー(non-terminating error)」として扱われ、実行は止まりません。try/catchは「終了エラー(terminating error)」しか捕捉しないため、既定のままではcatchに処理が渡らず、メッセージは出ているのに次の行へ進んでしまいます。

try {
    Get-Content -Path "C:\Scripts\notfound.txt"
} catch {
    Write-Output "エラーを検知しました: $($_.Exception.Message)"
}

このコードは、対象ファイルがなくても既定では非終了エラーのため、catchが実行されずメッセージだけ表示されて処理が続くことがあります。

-ErrorAction Stopとfinallyで確実に処理する

catchで確実に捕まえるには、対象コマンドに-ErrorAction Stopを付けて終了エラーに変換します。

try {
    Get-Content -Path "C:\Scripts\notfound.txt" -ErrorAction Stop
} catch {
    Write-Output "エラーを検知しました: $($_.Exception.Message)"
} finally {
    Write-Output "後片付け処理はここに書く"
}

$ErrorActionPreference = ‘Stop’を冒頭で設定する方法もありますが、他のコマンドの挙動まで変わることがあるため、まずは重要な処理単位ごとに-ErrorAction Stopを付ける方が影響範囲を把握しやすくなります。自動変数$Errorにはエラーが蓄積され、$Error[0]で直近の内容を確認できます。

モジュール不足・バージョン差によるエラー

Import-Moduleで「指定した名前の有効なモジュールが見つからない」という趣旨のエラーになるのもよくある話です。

モジュールが見つからない(PSModulePath)

Import-Moduleはパス省略時、環境変数$env:PSModulePathに登録されたフォルダーを再帰的に探索します。目的のモジュールがそこになければ見つからずエラーになります。フルパス指定でも回避できますが、恒久対応としてはモジュールを$env:PSModulePath配下に置くか、PSModulePathに配置先を追加します。

Import-Module -Name "C:\Scripts\Modules\SampleModule"

Install-Moduleが途中で止まる

PowerShell Gallery経由の取得にはNuGetプロバイダーが必要で、未導入だと初回実行時に自動インストールの確認を求められ、オフライン端末やプロキシ環境では止まりがちです。またPSGalleryは既定で「信頼されていないリポジトリ」扱いのため、初回のInstall-Moduleは確認プロンプトが出ます。自動化スクリプト内で止めたくない場合は、事前にリポジトリを信頼済みにしておきます。

Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
Install-Module -Name SampleModule -Scope CurrentUser

Windows PowerShell 5.1と7のモジュール互換性

5.1向けの一部モジュールは7でそのままでは動きません。7には「Windows PowerShell互換機能」があり、対象モジュールをバックグラウンドの5.1プロセス上で動かして橋渡ししますが、完全に同じ挙動になるとは限らないため、重要なスクリプトを7に移行する際は個別に検証が必要です。

Import-Module -Name ActiveDirectory -UseWindowsPowerShell

意味の分からないエラーに当たったら、Get-Help コマンド名 -Fullやオンラインヘルプ(-Online)で仕様を確認し、Update-Helpでローカルヘルプを最新化しておくと地味に効きます。インターネットに出られないサーバーでは、接続できる端末でSave-Helpを使って保存し、Update-Help -SourcePathで読み込ませます。

PowerShellのスクリプトを腰を据えて試すなら、汚しても作り直せる検証用サーバーが1台あると安心です。

XServer VPS の料金・スペックを見る ▶

まとめ

PowerShellの「動かない」「エラーが握りつぶされる」「文字化けする」といったトラブルの多くは、実行ポリシーのスコープ、5.1と7のエンコーディングの既定差、終了エラーと非終了エラーの違い、モジュールの探索パスを押さえていれば防げるか、原因の見当を早くつけられます。共通するのは、既定値に頼らず明示することです。実行ポリシーはスコープを、出力はエンコーディングを、エラー処理は-ErrorActionを、モジュールは配置場所とバージョン互換性を明示しておけば、実行環境が変わっても再現性のあるスクリプトになります。展開前にこの5点を一通りチェックすれば、本番でのトラブルはかなり減らせるはずです。

最終更新:2026年7月

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