将Powershell变量传递到Windows批处理文件 [英] Passing Powershell variable to Windows Batch file
问题描述
由于我的项目以及部署方式的限制,我需要在批处理文件中运行powershell命令,并从powershell脚本中回显变量.该脚本通过RS-232从电视上检索型号,并以十六进制形式返回该型号.
我编写了脚本,并将其精巧地压缩为可以运行的一行.我什至可以在命令行中使用"powershell -command"[myCondensedScript]",效果很好
/f %% a的 ,用于('powershell.exe -command"$ port = New-Object System.IO.Ports.SerialPort COM1,9600,none,8,one; [byte [] $reqSerial = 1,48,65,48,65,48,54,2,67,50,49,55,3,112,13; [byte []] $ reqModel = 0x01,0x30,0x41,0x30,0x41,0x30,0x36,0x02,0x43,0x32,0x31,0x37,0x03,0x70,0x0D; [byte []] $ response =''; [byte []] $ readData =''; $ port.DTREnable = $ True; $ port.Open(); $ port.Write($ reqModel,0,$ reqModel.Count); $ x = 0; do {$ x ++; $ readData = $ port.ReadChar(); If($ x -eq 13 -or$ x -eq 14-或$ x -eq 15-或$ x -eq 16-或$ x -eq 17-或$ x -eq 18-或$ x -eq 19-或$ x -eq 20-或$x -eq 21){$ response + = $ readData;};} while($ response.Length -ne 9); $ port.Close(); $ hexResponse = $ response.forEach([char]); $ hexResponseString =[string] $ hexResponse; $ hexResponseString = $ hexResponseString.replace('',''); $ finalHex = $ hexResponseString + 0; Write-Host $ finalHex;"^;(Get-Variable -ValueOnly -Name finalHex ^).值")将HexCode = %% a设置为回声%HexCode%
输出就是
echo +
预期输出为
<代码> 563332330
我不确定变量缺少什么,因为我对变量和批处理文件不是很熟练.我在Google上进行了广泛的搜索,发现此页面对 https://ss64.com/nt/for有所帮助.html 我只是不明白如何将%% a分配给我想要的确切变量.任何帮助将不胜感激!
您的命令已在封闭的'...'
字符串的上下文中未转义嵌入的'
字符,将无法正常工作.
相反,使用 usebackq
解析选项,然后将命令括在`...`
中,简化了引号和转义.
以下示例命令演示了该技术(要在 cmd.exe
提示符下尝试此方法,而不是从批处理文件中尝试,请将 %% a
替换为%a
):
上面打印了以下内容,证明嵌入的"..."
,'...'
和;
的工作原理如下:是(在使用"..."
的上下文中,将PowerShell命令传递给 -c
( -Command
)整体,这会阻止 cmd.exe
解释内容):
6969
使用 中的PowerShell命令传递到 -c
/-Command
参数(在 Windows PowerShell 中为隐含,但在PowerShell [Core] 6+中为必需).
- 由于
cmd.exe
无法解释"..."
字符串的内容(除了%...%
环境-可以直接使用cmd.exe
元字符(具有特殊句法含义的字符,例如&
).
单引号('
)可以原样使用.
如果需要在整个"..."
命令字符串中嵌入双引号("
):>
- 在PowerShell [Core] 6+(
pwsh.exe
)中,使用"
. - 在Windows PowerShell(
powershell.exe
)中,使用\"
,但请注意,然后将对字符串内部的空格进行标准化 (折叠成单个空间);\"
避免了这种情况,但随后要求您^
逸出任何cmd.exe
元字符,例如&
.
用于/f"usebackq delims =" %% i in(`REM在PowerShell [Core] 6+(pwsh.exe)中,使用"代替\"powershell -noprofile -c(\""hi& there \").Replace('i','@')"`)做@echo [%% i]
上面的结果(注意归一化的空格;在PowerShell [Core] 6+中带有"
的情况不会发生)
[hi&那里]
关于您的特定命令:
-
删除
^
(插入符号),因为使用......
引用不再需要它们;将整个传递给powershell -c
的命令包含在"..."
中. -
防止输出流受到污染,以确保仅返回感兴趣的值,这意味着:
-
删除
Write-Host
命令. -
将
$ null = ...
放在$ port.Open()
,$ port.Write(...)
,$ port.Close()
调用以确保它们不会隐式创建输出(请参见for /F %%a in ('powershell.exe -command "$port = New-Object System.IO.Ports.SerialPort COM1, 9600, none, 8, one;[byte[]] $reqSerial = 1,48,65,48,65,48,54,2,67,50,49,55,3,112,13;[byte[]] $reqModel = 0x01,0x30,0x41,0x30,0x41,0x30,0x36,0x02,0x43,0x32,0x31,0x37,0x03,0x70,0x0D;[byte[]] $response = '';[byte[]] $readData = '';$port.DTREnable = $True;$port.Open();$port.Write($reqModel, 0, $reqModel.Count);$x=0;do {$x++;$readData = $port.ReadChar();If($x -eq 13 -or $x -eq 14 -or $x -eq 15 -or $x -eq 16 -or $x -eq 17 -or $x -eq 18 -or $x -eq 19 -or $x -eq 20 -or $x -eq 21) {$response += $readData;};}while($response.Length -ne 9);$port.Close();$hexResponse = $response.forEach([char]);$hexResponseString = [string]$hexResponse;$hexResponseString = $hexResponseString.replace(' ','');$finalHex = $hexResponseString+0;Write-Host $finalHex;"^; (Get-Variable -ValueOnly -Name finalHex^).value') do set HexCode=%%a echo %HexCode%
The output is simply
echo +
The expected output would be
563332330
I'm not sure what I'm missing with the variable, as I'm not terribly skilled with variables and batch files. I have googled extensively and found this page to be somewhat helpful https://ss64.com/nt/for.html I just don't understand how I assign %%a to the exact variable I want. Any help would be greatly appreciated!
解决方案Your command has unescaped embedded
'
characters in the context of the enclosing'...'
string, which won't work.Instead, use the
usebackq
parsing option and enclose the command in`...`
, which simplifies quoting and escaping.The following sample command demonstrate the technique (to try this at the
cmd.exe
prompt instead of from a batch file, replace%%a
with%a
):for /f "usebackq delims=" %%a in (` powershell -c "$finalHex = '0x68 0x69' -replace '0x| '; $finalHex" `) do set "HexNum=%%a" echo %HexNum%
The above prints the following, proving that embedded
"..."
,'...'
, and;
worked as-is (in the context of using"..."
for the enclosing quoting around the PowerShell command passed to-c
(-Command
) as a whole, which preventscmd.exe
from interpreting the contents):6969
To summarize the
usebackq
rules with PowerShell's CLI:Pass the PowerShell commands enclosed in
"..."
as a whole to the-c
/-Command
parameter (which is implied in Windows PowerShell, but required in PowerShell [Core] 6+).- Since
cmd.exe
doesn't interpret the contents of"..."
strings (except%...%
environment-variable references),cmd.exe
metacharacters (characters with special syntactic meaning, e.g.,&
) can be used as-is.
- Since
Single quotes (
'
) can be used as-is.If you need to embed double quotes (
"
) inside the overall"..."
command string:- In PowerShell [Core] 6+ (
pwsh.exe
), use""
. - In Windows PowerShell (
powershell.exe
), use\""
, but note that string-internal whitespace will then be normalized (folded into a single space);\"
avoids that, but then requires you to^
-escape anycmd.exe
metacharacters such as&
.
- In PowerShell [Core] 6+ (
for /f "usebackq delims=" %%i in (` REM In PowerShell [Core] 6+ (pwsh.exe), use "" instead of \"" powershell -noprofile -c "(\""hi & there\"").Replace('i', '@')" `) do @echo [%%i]
The above yields (note the normalized whitespace; in PowerShell [Core] 6+ with
""
this wouldn't happen):[hi & there]
As for your specific command:
Remove the
^
(carets), as they are no longer needed with the`...`
quoting; enclose the commands passed topowershell -c
as a whole in"..."
.Prevent pollution of the output stream to make sure that only the value of interest is returned, which means:
Remove the
Write-Host
command.Place
$null = ...
before the$port.Open()
,$port.Write(...)
,$port.Close()
calls to make sure that they do not implicitly create output (see this answer for an explanation).
Simply use
$finalHex
by itself as the last statement in order to output it (no need for(Get-Variable ...)
).
这篇关于将Powershell变量传递到Windows批处理文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
-