我有一个无法更改的批处理脚本,因为它属于另一个应用程序。我想从 Powershell 调用该批处理脚本并访问变量值。这看起来是一个范围问题,也许我没有正确调用批处理脚本。我试过“&”、“invoke-expression”、“cmd /c”和“start-process”,但结果是一样的。这是简化的问题。
我有一个名为 batch.bat 的批处理脚本,其中包含两行:
set /p variable=what is the fruit:
echo %variable% (from batch)
我有一个 powershell 脚本包含:
$fp=resolve-path(".\batch.bat")
Invoke-Expression -Command "$fp"
write-host "$env:variable (from PS)"
来自命令提示符:
set variable=banana
powershell .\script.ps1
what is the fruit: orange
orange (from batch)
banana (from PS)
我希望橙色可以用于PS。如果我没有将变量预设为banana,那么PS将不会显示任何内容,因此它与预设值无关。我考虑过我可以编写另一个包装命令脚本来执行原始批处理脚本,然后将所有变量(以 PS 格式)写出到一个临时 .ps1 文件中,然后执行(点源)但它看起来很笨拙。
从 PowerShell 调用批处理文件必然会在 child process 中执行批处理文件,因为必须启动
cmd.exe
child process 才能执行它。
子进程根本无法修改其 caller 的环境变量。
您最好的选择是通过
cmd.exe /v /c
显式调用批处理文件,然后 echo 感兴趣的环境变量的 values,这允许 PowerShell 捕获它们:
$variableValue = cmd /v /c '.\batch.bat >&2 & echo !variable!'
"Value of %variable%: $variableValue"
/v
需要启用 delayed 变量扩展,这允许 echo
命令是调用 .\batch.bat
的同一语句的一部分动态报告后者设置的值,使用 !...!
而不是比%...%
包含变量引用。
.\batch.bat
的执行,因为 !
字符然后变成 元字符,除非它们故意包含变量引用 - 被悄悄删除.>&2
用于将 .\batch.bat
的 stdout 输出重定向到 stderr(流 2
),以便它仍然显示,但不会干扰 cmd /v c
输出到 stdout 的内容,这就是PowerShell 捕获。
如果要回显批处理文件退出后存在的 all 变量,作为
<name>=<value>
对,您使用以下内容,它通过 ConvertFrom-StringData
将名称-值对解析为单个hasthable :
# Assign to a variable ($hash = ...) as needed.
(cmd /c '.\batch.bat >&2 & set' | Out-String) -replace '\\', '\\' |
ConvertFrom-StringData