【bat】PowerShellをバッチファイルから呼び出す方法|連携パターンと使い分け

バッチファイル(.bat)は手軽ですが、日付の取得・JSON処理・HTTP通信・ZIP操作など少し高度なことをしようとすると限界があります。

そこで活躍するのが PowerShell をバッチから呼び出すパターンです。バッチの手軽さを保ちながら、PowerShell の豊富な機能を活用できます。

この記事では、基本の呼び出し方から変数への取り込み・文字コード対応・実行ポリシーの設定・実務パターンまで網羅的に解説します。

スポンサーリンク

バッチからPowerShellを呼び出す理由

観点 バッチ(bat) PowerShell
学習コスト 低い 中程度
日付・時刻の取得 環境依存で複雑 Get-Date で簡単
JSON/XMLの処理 困難 ConvertFrom-Json で容易
HTTP通信(REST API) 困難 Invoke-RestMethod で容易
ZIPファイル操作 困難 Compress-Archive で容易
既存スクリプトとの統合 容易 バッチから呼び出して統合

ポイント:既存のバッチを全部 PowerShell に書き換えるのは大変ですが、「難しい部分だけ PS に任せる」ハイブリッド構成が実務では最も現実的です。

基本の呼び出し方

バッチから PowerShell を呼び出す方法は主に3つあります。

basic-call.bat
@echo off

:: 方法1: -Command でインラインコマンドを実行
powershell -Command "Write-Host 'Hello from PowerShell'"

:: 方法2: -File で .ps1 スクリプトファイルを実行
powershell -File "C:Scriptsmyscript.ps1"

:: 方法3: -NoProfile -NonInteractive を付けた推奨形式
powershell -NoProfile -NonInteractive -Command "Get-Date"

よく使うオプション一覧

オプション 説明
-NoProfile プロファイルスクリプト($PROFILE)を読み込まない。起動が速くなり予期しない設定の影響を回避できる
-NonInteractive 対話的プロンプト(確認入力など)を表示しない。自動実行バッチには必須
-ExecutionPolicy Bypass スクリプト実行ポリシーをこの呼び出しだけ無効化する
-Command "..." ダブルクォートで囲んだ PS コマンドをインラインで実行
-File "path" .ps1 ファイルを実行する
-NoLogo 起動時のバナー(著作権情報)を非表示にする
-WindowStyle Hidden PowerShell ウィンドウを非表示で実行

インラインコマンドの実行

1行で完結する処理は -Command でインライン実行するのが最も手軽です。

inline-commands.bat
@echo off

:: 現在の日時を表示
powershell -NoProfile -Command "Get-Date -Format 'yyyy-MM-dd HH:mm:ss'"

:: ファイル一覧(最終更新日順)
powershell -NoProfile -Command "Get-ChildItem C:Data | Sort-Object LastWriteTime -Descending | Select-Object -First 10"

:: テキストファイルの行数をカウント
powershell -NoProfile -Command "(Get-Content C:data.csv).Count"

出力結果を変数に取り込む

PowerShell の出力をバッチ変数に取り込むには、FOR /F コマンドを使います。

capture-output.bat
@echo off
setlocal

:: PowerShell の出力を FOR /F で変数に取り込む
for /f "delims=" %%i in (
  'powershell -NoProfile -Command "Get-Date -Format 'yyyyMMdd'"'
) do set TODAY=%%i

echo 今日の日付: %TODAY%

:: ランダムな UUID を取得
for /f "delims=" %%i in (
  'powershell -NoProfile -Command "[guid]::NewGuid().ToString()"'
) do set UUID=%%i

echo UUID: %UUID%
endlocal

複数行のPowerShellを実行する

処理が複数行にわたる場合は、一時的な .ps1 ファイルを作成してから実行する方法が確実です。

multiline-ps.bat
@echo off
setlocal

:: 一時 .ps1 ファイルに複数行の PS コードを書き出す
set TMPPS=%TEMP%	mpscript.ps1

echo $src = "C:Data"          > "%TMPPS%"
echo $dst = "D:Backup"         >> "%TMPPS%"
echo $date = Get-Date -Format 'yyyyMMdd' >> "%TMPPS%"
echo $zip = Join-Path $dst "backup_$date.zip" >> "%TMPPS%"
echo Compress-Archive -Path $src -DestinationPath $zip -Force >> "%TMPPS%"
echo Write-Host "ZIP作成完了: $zip" >> "%TMPPS%"

:: .ps1 ファイルを実行
powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "%TMPPS%"

:: 一時ファイルを削除
del "%TMPPS%"
endlocal

文字コード対応(chcp 65001 + -OutputEncoding)

PowerShell の出力に日本語が含まれる場合、文字化けを防ぐための設定が必要です。

encoding.bat
@echo off

:: コードページを UTF-8 に切り替え
chcp 65001 >nul

:: PowerShell 側でも出力エンコーディングを UTF-8 に設定
powershell -NoProfile -Command ^
  "[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; Get-ChildItem C:\ | Select-Object -First 5"

:: または環境変数で設定(PowerShell 7.1 以降)
set PYTHONUTF8=1

補足:バッチファイル自体の保存文字コードも UTF-8(BOM なし)にしておくと、日本語混在環境での文字化けを最小化できます。ただし SHIFT-JIS 環境のサーバーでは chcp 65001 で不具合が出る場合もあるため、環境に合わせて使い分けてください。

実行ポリシーの設定

Windows のデフォルト設定では PowerShell スクリプト(.ps1)の実行がブロックされる場合があります。-ExecutionPolicy Bypass でこの呼び出し限りポリシーを回避できます。

execution-policy.bat
:: -ExecutionPolicy Bypass でポリシーを回避(この呼び出しのみ)
powershell -NoProfile -ExecutionPolicy Bypass -File "C:Scriptsdeploy.ps1"

:: 現在の実行ポリシーを確認
powershell -NoProfile -Command "Get-ExecutionPolicy -List"

:: 管理者権限でシステム全体の実行ポリシーを変更(永続的)
powershell -NoProfile -Command "Set-ExecutionPolicy RemoteSigned -Scope LocalMachine -Force"

注意:-ExecutionPolicy Bypass は便利ですが、悪意のあるスクリプトも実行できてしまいます。実行する .ps1 ファイルの内容を必ず確認した上で使用してください。社内の管理サーバーなど信頼できる環境での自動化に限定することをおすすめします。

実務パターン集

日付・時刻の取得(フォーマット指定)

get-date.bat
@echo off
setlocal

for /f "delims=" %%i in (
  'powershell -NoProfile -Command "Get-Date -Format 'yyyyMMdd_HHmmss'"'
) do set TIMESTAMP=%%i

echo タイムスタンプ: %TIMESTAMP%
:: 出力例: 20260312_143022
endlocal

ZIPファイルの作成

create-zip.bat
@echo off
setlocal

set SRC=C:ProjectsMyApp
set OUT=D:Releasesmyapp.zip

powershell -NoProfile -Command ^
  "Compress-Archive -Path '%SRC%' -DestinationPath '%OUT%' -Force"

echo ZIP作成完了: %OUT%
endlocal

REST API を呼び出す(JSONレスポンス処理)

call-api.bat
@echo off
setlocal

:: JSON を POST する例(Slack Webhook 通知)
set WEBHOOK=https://hooks.slack.com/services/XXXXX
set MSG=バックアップが完了しました

powershell -NoProfile -Command ^
  "Invoke-RestMethod -Uri '%WEBHOOK%' -Method Post -ContentType 'application/json' -Body '{"text":"バックアップが完了しました"}'"

endlocal

Slack/メール通知(一行でシンプルに)

send-mail.bat
@echo off

:: Send-MailMessage でメール送信(Exchange/SMTPサーバーが必要)
powershell -NoProfile -Command ^
  "Send-MailMessage -To 'admin@example.com' -From 'batch@example.com' -Subject 'バックアップ完了' -Body 'バックアップが正常に完了しました' -SmtpServer 'smtp.example.com'"

よくある失敗例と対処法

問題 原因・対処法
クォートが複雑でエラーになる -Command のダブルクォート内では PS のシングルクォートを使うか、一時 .ps1 ファイルに分離する
FOR /F で変数に取り込めない setlocal の有無と %%i の使い方を確認。CMD から直接実行する場合は %i(% ひとつ)になる
日本語が文字化けする chcp 65001 + [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 の両方を設定する
スクリプトの実行がブロックされる -ExecutionPolicy Bypass を追加するか、管理者権限で Set-ExecutionPolicy RemoteSigned を実行する
ERRORLEVEL が正しく取得できない PS 内で exit $LASTEXITCODE を明示的に実行するか、-Command の最後に “; exit $LASTEXITCODE” を追加する

FAQ

❓ バッチと PowerShell、どちらで書くべきですか? (クリックで開閉)

単純なファイル操作・コマンド実行・サービス管理程度ならバッチで十分です。JSON/XML処理・HTTP通信・ZIPファイル・複雑な文字列処理が必要な場合は PowerShell を使います。既存のバッチ資産がある場合は、難しい部分だけ PowerShell を呼び出すハイブリッド構成が最も現実的です。新規開発ならば最初から PowerShell (.ps1) で書くことをおすすめします。

❓ PowerShell 5 と PowerShell 7 の違いは? (クリックで開閉)

PowerShell 5(Windows PowerShell)は Windows に標準搭載されており、コマンドは powershell です。PowerShell 7(PowerShell Core)はクロスプラットフォーム対応の新版で、コマンドは pwsh です。バッチから呼び出す場合、Windows 標準環境では powershell が確実に使えます。PowerShell 7 を使う場合は別途インストールが必要です。

❓ タスクスケジューラから PowerShell を含むバッチを実行する注意点は? (クリックで開閉)

タスクスケジューラでバッチを実行する際は、-NonInteractive オプションを必ず付けてください。プロンプトで処理が止まることを防げます。また「開始する場所」にバッチファイルのディレクトリを設定すると、相対パスが正しく解決されます。PowerShell ウィンドウを非表示にしたい場合は -WindowStyle Hidden を追加してください。