Noções básicas sobre a codificação de arquivos no VS Code e no PowerShell
Ao usar o VS Code para criar e editar scripts do PowerShell, é importante que seus arquivos sejam salvos usando o formato de codificação de caractere correto.
O que é codificação de arquivo e por que é importante?
O VS Code gerencia a interface entre um humano que insere cadeias de caracteres em um buffer e blocos de leitura/gravação de bytes no sistema de arquivos. Quando o VS Code salva um arquivo, ele usa uma codificação de texto para decidir quais bytes cada caractere se torna. Para obter mais informações, consulte about_Character_Encoding.
Da mesma forma, quando o PowerShell executa um script, ele deve converter os bytes em um arquivo em caracteres para reconstruir o arquivo em um programa do PowerShell. Como o VS Code grava o arquivo e o PowerShell lê o arquivo, ele precisa usar o mesmo sistema de codificação. Esse processo de análise de um script do PowerShell vai: bytes ->caracteres - tokens> -> de árvore de sintaxe abstrata ->de execução .
O VS Code e o PowerShell são instalados com uma configuração de codificação padrão sensata. No entanto, a codificação padrão usada pelo PowerShell foi alterada com a versão do PowerShell 6. Para garantir que você não tenha problemas ao usar o PowerShell ou a extensão do PowerShell no VS Code, você precisa definir as configurações do VS Code e do PowerShell corretamente.
Causas comuns de problemas de codificação
Problemas de codificação ocorrem quando a codificação do VS Code ou seu arquivo de script não corresponde à codificação esperada do PowerShell. Não há como o PowerShell determinar automaticamente a codificação de arquivo.
É mais provável que você tenha problemas de codificação quando estiver usando caracteres que não estão no conjunto de caracteres ASCII de 7 bits . Por exemplo:
- Caracteres não-letra estendidos, como em-dash (
—
), espaço sem interrupção ("
) - Caracteres latinos acentuados (
É
,ü
) - Caracteres não latinos como Cirílico (
Д
,Ц
) - Caracteres CJK (
本
,화
,が
)
Os motivos comuns para problemas de codificação são:
- As codificações do VS Code e do PowerShell não foram alteradas de seus padrões. Para o PowerShell 5.1 e abaixo, a codificação padrão é diferente da do VS Code.
- Outro editor abriu e substituiu o arquivo em uma nova codificação. Isso geralmente acontece com o ISE.
- O arquivo é verificado no controle do código-fonte em uma codificação diferente do que o VS Code ou o PowerShell espera. Isso pode acontecer quando os colaboradores usam editores com configurações de codificação diferentes.
Como saber quando você tem problemas de codificação
Geralmente, erros de codificação apresentam-se como erros de análise em scripts. Se você encontrar sequências de caracteres estranhas em seu script, esse pode ser o problema. No exemplo a seguir, um en-dash (–
) aparece como os caracteres â€"
:
Send-MailMessage : A positional parameter cannot be found that accepts argument 'Testing FuseMail SMTP...'.
At C:\Users\<User>\<OneDrive>\Development\PowerShell\Scripts\Send-EmailUsingSmtpRelay.ps1:6 char:1
+ Send-MailMessage â€"From $from â€"To $recipient1 â€"Subject $subject ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Send-MailMessage], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.SendMailMessage
Esse problema ocorre porque o VS Code codifica o caractere –
em UTF-8 à medida que os bytes 0xE2 0x80 0x93
. Quando esses bytes são decodificados como Windows-1252, eles são interpretados como os caracteres â€"
.
Algumas sequências de caracteres estranhas que você pode ver incluem:
-
â€"
em vez de–
(um en-dash) -
â€"
em vez de—
(um traço em) -
Ä2
em vez deÄ
-
Â
em vez de -
é
em vez deé
Este de referência útil lista os padrões comuns que indicam um problema de codificação UTF-8/Windows-1252.
Como a extensão do PowerShell no VS Code interage com codificações
A extensão do PowerShell interage com scripts de várias maneiras:
- Quando os scripts são editados no VS Code, o conteúdo é enviado pelo VS Code para a extensão. O do
Language Server determina que esse conteúdo seja transferido em UTF-8. Portanto, não é possível que a extensão obtenha a codificação errada. - Quando os scripts são executados diretamente no Console Integrado, eles são lidos diretamente do arquivo pelo PowerShell. Se a codificação do PowerShell for diferente da do VS Code, algo poderá dar errado aqui.
- Quando um script aberto no VS Code faz referência a outro script que não está aberto no VS Code, a extensão volta a carregar o conteúdo desse script do sistema de arquivos. A extensão do PowerShell usa como padrão a codificação UTF-8, mas usa marca de ordem de byte, ou BOM, detecção para selecionar a codificação correta.
O problema ocorre ao assumir a codificação de formatos sem BOM (como UTF-8 sem BOM e Windows-1252). A extensão do PowerShell usa como padrão UTF-8. A extensão não pode alterar as configurações de codificação do VS Code. Para obter mais informações, consulte problema nº 824.
Escolhendo a codificação certa
Diferentes sistemas e aplicativos podem usar codificações diferentes:
- No .NET Standard, na Web e no mundo linux, UTF-8 agora é a codificação dominante.
- Muitos aplicativos do .NET Framework usam UTF-16. Por motivos históricos, isso às vezes é chamado de "Unicode", um termo que agora se refere a uma ampla padrão que inclui UTF-8 e UTF-16.
- No Windows, muitos aplicativos nativos que antecedem o Unicode continuam a usar o Windows-1252 por padrão.
As codificações Unicode também têm o conceito de uma marca de ordem de bytes (BOM). Os BOMs ocorrem no início do texto para informar a um decodificador qual codificação o texto está usando. Para codificações de vários bytes, o BOM também indica de endianidade da codificação. Os BOMs são projetados para serem bytes que raramente ocorrem em texto não Unicode, permitindo um palpite razoável de que o texto é Unicode quando um BOM está presente.
Os BOMs são opcionais e sua adoção não é tão popular no mundo linux porque uma convenção confiável do UTF-8 é usada em todos os lugares. A maioria dos aplicativos Linux presume que a entrada de texto está codificada em UTF-8. Embora muitos aplicativos Linux reconheçam e manipulem corretamente um BOM, um número não o faz, levando a artefatos em texto manipulados com esses aplicativos.
Portanto,:
- Se você trabalha principalmente com aplicativos windows e Windows PowerShell, você deve preferir uma codificação como UTF-8 com BOM ou UTF-16.
- Se você trabalha entre plataformas, deve preferir UTF-8 com BOM.
- Se você trabalha principalmente em contextos associados ao Linux, deve preferir UTF-8 sem BOM.
- O Windows-1252 e o latin-1 são essencialmente codificações herdadas que você deve evitar, se possível. No entanto, alguns aplicativos mais antigos do Windows podem depender deles.
- Também vale a pena observar que a assinatura de script é dependente de codificação, o que significa que uma alteração da codificação em um script assinado exigirá a demissão.
Configurando o VS Code
A codificação padrão do VS Code é UTF-8 sem BOM.
Para definir de codificação do VS Code, vá para as configurações do VS Code (+Ctrl,) e defina a configuração de "files.encoding"
:
"files.encoding": "utf8bom"
Alguns valores possíveis são:
-
utf8
: [UTF-8] sem BOM -
utf8bom
: [UTF-8] com BOM -
utf16le
: Pequeno endian [UTF-16] -
utf16be
: Big Endian [UTF-16] -
windows1252
: [Windows-1252]
Você deve obter uma lista suspensa para isso no modo de exibição gui ou conclusões para ele no modo de exibição JSON.
Você também pode adicionar o seguinte à codificação de detecção automática quando possível:
"files.autoGuessEncoding": true
Se você não quiser que essas configurações afetem todos os tipos de arquivos, o VS Code também permite configurações por idioma. Crie uma configuração específica do idioma colocando as configurações em um campo [<language-name>]
. Por exemplo:
"[powershell]": {
"files.encoding": "utf8bom",
"files.autoGuessEncoding": true
}
Talvez você também queira considerar a instalação do do rastreador Gremlins para Visual Studio Code. Essa extensão revela determinados caracteres Unicode facilmente corrompidos porque são invisíveis ou se parecem com outros caracteres normais.
Configurando o PowerShell
A codificação padrão do PowerShell varia dependendo da versão:
- No PowerShell 6+, a codificação padrão é UTF-8 sem BOM em todas as plataformas.
- No Windows PowerShell, a codificação padrão geralmente é o Windows-1252, que é uma extensão de latin-1 (também conhecido como ISO 8859-1).
No PowerShell 5+, você pode encontrar sua codificação padrão com isso:
[psobject].Assembly.GetTypes() | Where-Object { $_.Name -eq 'ClrFacade'} |
ForEach-Object {
$_.GetMethod('GetDefaultEncoding', [System.Reflection.BindingFlags]'nonpublic,static').Invoke($null, @())
}
O script de a seguir pode ser usado para determinar qual codificação sua sessão do PowerShell infere para um script sem um BOM.
$badBytes = [byte[]]@(0xC3, 0x80)
$utf8Str = [System.Text.Encoding]::UTF8.GetString($badBytes)
$bytes = [System.Text.Encoding]::ASCII.GetBytes('Write-Output "') + [byte[]]@(0xC3, 0x80) + [byte[]]@(0x22)
$path = Join-Path ([System.IO.Path]::GetTempPath()) 'encodingtest.ps1'
try
{
[System.IO.File]::WriteAllBytes($path, $bytes)
switch (& $path)
{
$utf8Str
{
return 'UTF-8'
break
}
default
{
return 'Windows-1252'
break
}
}
}
finally
{
Remove-Item $path
}
É possível configurar o PowerShell para usar uma determinada codificação de modo mais geral usando configurações de perfil. Consulte os seguintes artigos:
- @mklement0resposta sobre a codificação do PowerShell no Stack Overflow.
- @rkeithhillpostagem no blog sobre como lidar com entrada UTF-8 sem BOM no PowerShell.
Não é possível forçar o PowerShell a usar uma codificação de entrada específica. O PowerShell 5.1 e abaixo, em execução no Windows com a localidade definida como en-US, usa como padrão a codificação do Windows-1252 quando não há BOM. Outras configurações de localidade podem usar uma codificação diferente. Para garantir a interoperabilidade, é melhor salvar scripts em um formato Unicode com um BOM.
Importante
Quaisquer outras ferramentas que você tenha que toquem em scripts do PowerShell podem ser afetadas por suas opções de codificação ou recodificar seus scripts para outra codificação.
Scripts existentes
Os scripts que já estão no sistema de arquivos podem precisar ser codificados novamente para a nova codificação escolhida. Na barra inferior do VS Code, você verá o rótulo UTF-8. Clique nele para abrir a barra de ações e selecione Salvar comde codificação. Agora você pode escolher uma nova codificação para esse arquivo. Consulte de codificação do VS Code para obter instruções completas.
Se você precisar recodificar vários arquivos, poderá usar o seguinte script:
Get-ChildItem *.ps1 -Recurse | ForEach-Object {
$content = Get-Content -Path $_
Set-Content -Path $_.Fullname -Value $content -Encoding UTF8 -PassThru -Force
}
O ISE (Ambiente de Script Integrado) do PowerShell
Se você também editar scripts usando o ISE do PowerShell, precisará sincronizar suas configurações de codificação lá.
O ISE deve honrar um BOM, mas também é possível usar a reflexão para definir a codificação. Observe que isso não seria mantido entre as inicializações.
Software de controle do código-fonte
Algumas ferramentas de controle do código-fonte, como o git, ignoram codificações; git apenas rastreia os bytes. Outros, como o Azure DevOps ou o Mercurial, podem não. Até mesmo algumas ferramentas baseadas em git dependem da decodificação de texto.
Quando esse for o caso, certifique-se de:
- Configure a codificação de texto no controle do código-fonte para corresponder à configuração do VS Code.
- Verifique se todos os seus arquivos estão verificados no controle do código-fonte na codificação relevante.
- Tenha cuidado com as alterações na codificação recebidas por meio do controle do código-fonte. Um sinal chave disso é uma diferença que indica alterações, mas onde nada parece ter mudado (porque os bytes têm, mas os caracteres não mudaram).
Ambientes de colaboradores
Além de configurar o controle do código-fonte, verifique se os colaboradores em todos os arquivos compartilhados não têm configurações que substituam sua codificação codificando novamente arquivos do PowerShell.
Outros programas
Qualquer outro programa que lê ou grava um script do PowerShell pode codificá-lo novamente.
Alguns exemplos são:
- Usando a área de transferência para copiar e colar um script. Isso é comum em cenários como:
- Copiando um script para uma VM
- Copiando um script de um email ou página da Web
- Copiando um script para dentro ou para fora de um documento do Microsoft Word ou do PowerPoint
- Outros editores de texto, como:
- Bloco de notas
- vim
- Qualquer outro editor de scripts do PowerShell
- Utilitários de edição de texto, como:
Get-Content
/Set-Content
/Out-File
- Operadores de redirecionamento do PowerShell, como
>
e>>
sed
/awk
- Programas de transferência de arquivo, como:
- Um navegador da Web ao baixar scripts
- Um compartilhamento de arquivos
Algumas dessas ferramentas lidam com bytes em vez de texto, mas outras oferecem configurações de codificação. Nesses casos em que você precisa configurar uma codificação, você precisa torná-la igual à codificação do editor para evitar problemas.
Outros recursos na codificação no PowerShell
Há algumas outras postagens interessantes sobre codificação e configuração de codificação no PowerShell que valem a pena ler:
- about_Character_Encoding
- resumo do @mklement0da codificação do PowerShell no Stack Overflow
- Problemas anteriores abertos no VS Code-PowerShell para problemas de codificação:
- O clássico Joel no Software gravar sobre Unicode
- codificação no .NET Standard