batからPowerShellへの移行判断の知識マップ(知識グラフ)
この記事は、社内に残るバッチファイル(bat)をPowerShellへ移行すべきかを判断する基準を整理する。cmd.exeとbatに廃止予定はなくPowerShellが自動化の推奨手段とされる一方、VBScriptは非推奨化され将来削除される計画が公式に示されており、cscript/wscriptでVBScriptを呼ぶbatは優先移行の対象になる。batはエラーで止まらず%ERRORLEVEL%の判定にも罠があるのに対し、PowerShellはtry/catch・-WhatIf・Pesterで失敗の検知と安全な予行演習とテストを提供する。移行期は入口batからpowershell.exeやpwshを-Fileで呼び出し終了コードを引き継ぐ構成が現実解で、実行ポリシーはグループポリシーなどで統一するのが本筋とされ、robocopyのような実績ある外部コマンドは書き換えずそのまま呼び出すべきとされる。
バッチファイル(bat)
cmd.exeが解釈するコマンドを並べたスクリプトファイル。拡張子.batまたは.cmdを持つ。
cmdスクリプト
PowerShell
オブジェクトパイプラインとエラー処理機構を持つ、Microsoftが最も堅牢で最新のWindows自動化に推奨するコマンドラインシェル兼スクリプト言語。
コマンドシェル(cmd.exe)
Windowsに搭載される、batファイルなどのバッチスクリプトを実行する伝統的なコマンドラインシェル。
コマンドプロンプト
Windowsの自動化
コマンドやスクリプトによってWindows上の作業を自動化する用途領域。Microsoftは最も堅牢で最新の自動化にPowerShellの使用を推奨している。
VBScript
cscript/wscriptで実行される、2023年10月に非推奨が発表されたMicrosoftのスクリプト言語。今後のWindowsで要求時インストール化を経てOSから削除される計画が公開されている。
batのエラー無停止(握りつぶし)
cmdが既定でコマンド失敗時も次の行へ進み、判定を書かなければ失敗が検知されずに処理が続行されるbatの性質。
%ERRORLEVEL%の罠
if errorlevel Nが『N以上』の判定であることと、%errorlevel%が同名の環境変数を定義すると壊れるという、batの終了コード判定の落とし穴。
ERRORLEVEL環境変数の罠
終了コード(exit code)
プロセスが終了時に返す整数値。bat側は%ERRORLEVEL%、PowerShell側はexitキーワードや$LASTEXITCODEで扱う。
入口batからPowerShellを呼ぶ構成
既存のbatをジョブ管理との接点として残しつつ、-Fileパラメーターで中身のPowerShellスクリプトを呼び出し、終了コードを引き継ぐ移行期の構成。
混在期のラッパー構成
PowerShell実行ポリシー
PowerShellスクリプトの実行可否と署名要求を制御する設定。既定はクライアントOSでRestricted、Windows ServerとPowerShell 7ではRemoteSigned。
グループポリシー
Active Directoryドメイン環境でWindowsの設定を集中構成する仕組み。
robocopy
リトライ(既定100万回)・ミラーリング・ログ機能を持つ、Windows標準のファイルコピー用コマンドラインツール。0〜8以上という独特の終了コード体系を持つ。
PowerShellのtry/catch
文終了エラーやスクリプト終了エラーを捕捉し、finallyで後始末を書けるPowerShellのエラー処理構文。
-WhatIfパラメーター
システムやデータを変更するコマンドレットが提供する、実行せずに影響だけを表示する共通パラメーター。
Pester
PowerShellスクリプトの自動テストを書くためのテストフレームワーク。
batファイルはcmd.exeが解釈・実行するスクリプトファイルである
Microsoftは最も堅牢で最新のWindows自動化にはコマンド(cmd)やWindows Script HostではなくPowerShellの使用を推奨すると明記している
VBScriptは2023年10月に非推奨が正式発表され、要求時インストール化を経てOSから削除される計画が公開されており、新規の自動化用途には推奨されない
Microsoftの公式ドキュメントは最も堅牢で最新のWindows自動化にPowerShellの使用を推奨すると明記している
batの一部はcscript/wscriptでVBScriptを呼び出す構成になっており、2000年代の定番パターンとして今も残っている
cmdは既定でコマンドが失敗しても次の行へ進むため、判定を書き忘れたbatの失敗は静かに握り潰される
if errorlevel 1は『1以上』の判定であり、%errorlevel%は同名の環境変数を定義すると壊れるため、batの終了コード判定は誤りやすい
batはexit /b <exitcode>でERRORLEVEL環境変数に終了コードを設定する
PowerShellのexitキーワードは$LASTEXITCODEを設定し、pwsh -Fileで実行したスクリプトの終了コードは呼び出し元の%ERRORLEVEL%として観測される
入口batはpowershell.exeまたはpwshを-Fileパラメーターで呼び出し、%~dp0で自身のフォルダを解決する
入口bat構成は終了コードをbatとPowerShellの間で引き継ぎ、既存のジョブ管理を保ったまま中身をPowerShell化できる
PowerShellスクリプトの実行は実行ポリシーの制約を受ける。既定値は環境で異なり、Windows PowerShell 5.1のクライアントOSではRestricted(スクリプト実行不可)、Windows ServerとPowerShell 7ではRemoteSignedである。RemoteSignedの場合、インターネット由来のマーク付き未署名スクリプトはブロックされる
実行ポリシーの恒久的な統一はグループポリシーで行うのが本筋とされ、bat側で-ExecutionPolicy Bypassを付ける方法は管理者が構成したポリシーを弱めてしまう。ドメイン参加環境でグループポリシーを配布している場合に限る
PowerShellはrobocopyのような実績ある外部コマンドをそのまま呼び出せるため、Copy-Itemでの再実装は不要とされる
robocopyは0〜8以上という独特の終了コード体系を持ち、8以上が失敗を意味するため$LASTEXITCODEでの判定が必要になる
PowerShellはtry/catch/finallyで文終了エラーとスクリプト終了エラーを構造的に処理できる
PowerShellのtry/catchはbatが起こしていた『エラーで止まらない』問題を構造的に解消する
PowerShellの破壊的操作を行うコマンドレットのうち、SupportsShouldProcessを宣言してShouldProcessを呼ぶものに限り、-WhatIfで実行せずに影響を予告表示できる共通パラメーターを持つ。外部コマンドの呼び出しには自動では付かない
移行したスクリプトを自動テストで守る場合、Pesterで『動くはず』を継続的に確認できる。自動テストを持たないスクリプトや、対話的に流すだけの用途では使わない。
移行期の入口bat構成は既存のbatファイルをジョブ管理との接点として残し、中身だけをPowerShellに置き換える