quando eu corro
Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName, DisplayVersion, Publisher, InstallDate | Format-Table –AutoSize
diretamente do PowerShell, o código funciona bem.
No entanto, quando coloquei esse código exato no arquivo script.txt
e executei
$stdout = Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Get-Content 'script.txt'))) *>&1
Recebi o seguinte erro:
Exception calling "Create" with "1" argument(s): "At line:1 char:163
+ ... me, DisplayVersion, Publisher, InstallDate | Format-Table –AutoSize
+ ~~~~~~~~~
The string is missing the terminator: "."
O que causa esse comportamento? Como devo ajustar o código para poder executar o script do arquivo txt externo?
tl;dr
A implicação é que você está usando o Windows PowerShell e que há um problema de codificação de caracteres .
(O problema não surgiria no PowerShell (Core) 7+ , cuja codificação padrão consistente é agora (sem BOM) UTF-8.)
Você tem duas opções de solução :
Ou: Salve novamente seu
script.txt
arquivo como UTF-8 com BOM .Ou: Use
-Encoding utf8
com suaGet-Content
chamada (observe o alerta de bug abaixo):Uma alternativa mais simples é usar
Invoke-Expression
( no entanto, geralmente é melhor evitar o uso ):Alerta de bug :
Ao combinar os comentários acima com o redirecionamento
*>&1
, a saída de erro , especificamente, desaparece , ou seja, inesperadamente não é mesclada no fluxo de saída de sucesso (1
).Isso se aplica ao Windows PowerShell (onde não será corrigido) e ao PowerShell (Core) até pelo menos v7.3.6; o relatório de bug relevante é o problema nº 10476 do GitHub .
Uma solução alternativa é colocar a
Invoke-Command
chamada ou oInvoke-Expression
pipeline em(...)
, o operador de agrupamento antes de aplicar*>&1
, por exemplo:A solução alternativa tem um efeito colateral : Usar
(...)
significa que toda a saída do comando incluído é coletada na memória primeiro, na íntegra , antes que o redirecionamento seja aplicado e a saída seja produzida.Informações básicas:
Parece que seu arquivo
script.txt
está codificado em UTF-8, mas não possui um BOM , o que faz com que o Windows PowerShell interprete incorretamente seu arquivo como codificado em ANSI (ou seja, usando a página de código ANSI de byte único da localidade herdada de seu sistema).Não é óbvio, mas seu arquivo contém um caractere não ASCII:
O
–
in–AutoSize
é o EN DASH,U+2013
caractere, não o caractere usual de intervalo ASCII-
,-
(HÍFEN-MENOS,U+002D
).Quando a codificação UTF-8 de 3 bytes
–
é mal interpretada como ANSI, cada byte se torna um caractere por si só, especificamente:–
É a
“
(ASPA DUPLA ESQUERDA,U+201C
) - que o PowerShell aceita como alternativa às aspas duplas usuais do intervalo ASCII, ASPA, - que causa o erro de sintaxe, porque faltaU+0022
uma aspa dupla de fechamento .Da mesma forma, o PowerShell aceita
-
(EN DASH) no lugar do intervalo ASCII-
.Para obter a lista completa de caracteres intercambiáveis de aspas e pontuação com função sintática suportada pelo PowerShell, consulte esta resposta .
No entanto, para robustez, geralmente é melhor usar os caracteres do intervalo ASCII.
Os remédios na seção superior evitam o problema.