バッチファイル(.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 を追加してください。