Windows のバッチファイルから PowerShell コード実行


Windows のバッチファイル内に PowerShell コードを埋め込み

foo.cmd として保存し、バッチファイルから PowerShell コードを実行する。

<# : batch portion
@echo off
setlocal
powershell -noprofile -nologo -command "icm -ScriptBlock ([scriptblock]::Create((Get-Content '%~f0' -Raw))) -Args '%~f0'"
exit /b
: end batch / begin powershell #>

# PowerShell code
Write-Host "Hello from PowerShell!" -ForegroundColor Cyan

1行目の < はバッチでは無視され、: end batch / begin powershell #> も同様にラベル表記として無視される

<# ... #> は PowerShell から見ると複数行コメント

バッチから powershell コマンドで PowerShell を起動

Get-Content '%~f0' -Raw では %~f0 が実行されているバッチファイル自身のフルパスを表すため、パスを文字列として取得

[scriptblock]::Create(...) でバッチファイル自身を実行可能なスクリプトブロックに変換(この時<# ... #> はコメントとなるため、PowerShell のスクリプトコードとなる)

icm -ScriptBlock ... -Args '%~f0' で生成したスクリプトブロックを即時実行(-Args を渡すことで、PowerShell 側で $args[0] として自分自身のファイルパス等を利用できる)


Windows のバッチファイル内の PowerShell コードの結果をバッチ側で処理する

バッチファイルからPowerShell コードを実行(必要ファイルのダウンロードなど)し、PowerShell 側で構築したコマンドをバッチ側で実行する。

<# : batch portion
@echo off
setlocal enabledelayedexpansion

:: 1. 環境変数の退避と初期化
set "__MY_ARG0_=%~nx0"
set "__FINAL_CMD__="
set "__PS_SAVE_PATH__=%PSModulePath%"
set "PSModulePath="

:: 2. PowerShell の実行と出力のパース
:: PowerShell 側で "FINAL_CMD=実行したいコマンド" と出力するとバッチ変数に格納される
for /f "usebackq tokens=1* delims==" %%A in (`powershell -noprofile -executionpolicy bypass -command "& {$scriptDir='%~dp0'; $script='%__MY_ARG0_%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) do (
    if "%%A"=="FINAL_CMD" (
        set "__FINAL_CMD__=%%B"
    ) else if "%%B"=="" (
        echo %%A
    ) else (
        echo %%A=%%B
    )
)

:: 3. 環境変数の復元
set "PSModulePath=%__PS_SAVE_PATH__%"

:: 4. PowerShellで指定したコマンドの実行
if not "%__FINAL_CMD__%"=="" (
    %__FINAL_CMD__% %*
    exit /b %ERRORLEVEL%
)

echo [ERROR] Cannot start command >&2
exit /b 1

: end batch / begin powershell #>

# PowerShell code
# 何等かの事前処理を行いバッチ側で実行するコマンドを構築
$targetApp = Join-Path $scriptDir "bin\myapp.exe"

# バッチ側に渡したい実行コマンドを "FINAL_CMD=..." の形式で出力
Write-Output "FINAL_CMD=$targetApp"

# バッチ側ループで echoされる
Write-Output "Status: PowerShell logic completed."