Передача переменной Powershell в Windows командный файл - PullRequest
1 голос
/ 28 февраля 2020

Из-за ограничений, связанных с моим проектом и тем, как он развертывается, мне нужно запустить команду powershell в командном файле и вывести переменную из сценария powershell. Эти сценарии извлекают номер модели из телевизора через RS-232 и возвращают модель в HEX.

Я написал сценарий и дотошно сжал его до одной бегущей строки. Я могу даже 'powershell -command "[myCondensedScript]"' в командной строке, и она прекрасно работает

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%

Выход просто

   echo +

Ожидаемый результат будет

563332330

Я не уверен, что мне не хватает с переменной, так как я не очень разбираюсь в переменных и пакетных файлах. Я много гуглил и нашел эту страницу несколько полезной https://ss64.com/nt/for.html Я просто не понимаю, как назначить %% a именно той переменной, которую я хочу. Любая помощь будет принята с благодарностью!

Ответы [ 3 ]

1 голос
/ 28 февраля 2020

В вашей команде есть неэкранированные внедренные ' символы в контексте вложенной строки '...', которая не будет работать.

Вместо этого использует параметр синтаксического анализа usebackq и заключите команду в `...`, что упрощает кавычки и экранирование.

В следующем примере команды демонстрируется метод (чтобы попробовать это в приглашении cmd.exe вместо командного файла , замените %%a на %a):

for /f "usebackq delims=" %%a in (`
  powershell -c "$finalHex = '0x68 0x69' -replace '0x| '; $finalHex"
`) do set "HexNum=%%a"
echo %HexNum%

Выше напечатано следующее, доказав, что встроенные "...", '...' и ; работали как есть (в контексте используя "..." для заключающего в кавычки команд PowerShell, переданных в -c (-Command) в целом, что не позволяет cmd.exe интерпретировать содержимое):

6969

To Суммируйте правила usebackq с помощью CLI PowerShell :

  • Передайте команды PowerShell, заключенные в "..." в целом * От 1041 * до параметра -c / -Command (что подразумевается * in Windows PowerShell , но требуется в PowerShell [Core] 6+).

    • Поскольку cmd.exe не интерпретирует содержимое "..." строк (кроме %...% ссылки на переменные среды), cmd.exe метасимволы (символы со специальным синтаксисом c, означающим, например, &), могут использоваться как есть.
  • Одиночные кавычки (') можно использовать как есть.

  • Если вам нужно вставлять двойные кавычки (") внутри общего "..." командная строка:

    • В PowerShell [Core] 6+ (pwsh.exe) используйте "".
    • В Windows PowerShell (powershell.exe) используйте \"", но учтите, что пробел во внутренней строке будет тогда нормализован (сложен в один пробел); \" избегает этого, но затем требует от вас ^ -перекрыть любые cmd.exe метасимволы, такие как &.
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]

Выше приведены результаты (примечание нормализованный пробел; в PowerShell [Core] 6+ с "" этого не произойдет):

[hi & there]

Что касается вашей указанной c команды :

  • Удалите ^ (каретки), так как они больше не нужны с цитатой `...`; заключить команды, переданные в powershell -c в целом в "...".

  • Предотвратить загрязнение выходного потока, чтобы убедиться, что только интересующее значение возвращается, что означает:

    • Удалите команду Write-Host.

    • Поставьте $null = ... перед $port.Open(), $port.Write(...), $port.Close() вызывает, чтобы убедиться, что они не неявно создают вывод (см. этот ответ для объяснения).

  • Просто используйте $finalHex отдельно как последний оператор для его вывода (не нужно (Get-Variable ...)).

0 голосов
/ 29 февраля 2020

Если это работает в powershell, вы можете попытаться вернуть его обратно в имеющуюся командную строку.

$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
0 голосов
/ 28 февраля 2020

Я проанализировал часть PowerShell. Две каретки, ^, в конце не имеют смысла для меня. Можете ли вы объяснить их смысл? Посмотрите на последнюю строчку чуть ближе.

# 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...