Passing Powershell variable to Windows Batch file

五迷三道 提交于 2021-02-08 09:16:30

问题


Due to restrictions around my project and how this is being deployed, I need to run a powershell command in a batch file and echo a variable from the powershell script. This scripts retrieves a model number from a TV over RS-232 and returns the model in HEX.

I wrote the script and meticulously condensed it to one line that runs. I can even 'powershell -command "[myCondensedScript]"' in the command line and it works great

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!


回答1:


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 prevents cmd.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.
  • 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 any cmd.exe metacharacters such as &.
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 to powershell -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 ...)).




回答2:


I parsed the powershell part of it. The two carets, ^, at the end do not make sense to me. Can you explain the point of them? Look at the last line a little closer.

# Removed " from "$Port below

$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



回答3:


If this works in powershell then you can try to put it back into the command line you have.

$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;
(Get-Variable -ValueOnly -Name finalHex).value


来源:https://stackoverflow.com/questions/60442926/passing-powershell-variable-to-windows-batch-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!