Principy kódování souborů ve VS Code a PowerShellu

Při vytváření a úpravě skriptů PowerShellu pomocí nástroje VS Code je důležité, aby se soubory ukládaly pomocí správného formátu kódování znaků.

Co je kódování souborů a proč je důležité?

VS Code spravuje rozhraní mezi člověkem, který zadává řetězce znaků do vyrovnávací paměti a bloky čtení a zápisu bajtů do systému souborů. Když VS Code uloží soubor, použije kódování textu k rozhodnutí, jaké bajty se jednotlivé znaky stanou. Další informace najdete v tématu about_Character_Encoding.

Podobně když PowerShell spustí skript, musí převést bajty v souboru na znaky, aby se soubor rekonstruoval do programu PowerShellu. Vzhledem k tomu, že VS Code zapisuje soubor a PowerShell soubor čte, musí používat stejný systém kódování. Tento proces analýzy skriptu PowerShellu probíhá: bajty ->characters -tokens ->>abstract syntax tree ->execution.

VS Code i PowerShell se instalují s rozumnou výchozí konfigurací kódování. Výchozí kódování používané PowerShellem se ale změnilo s vydáním PowerShellu 6. Abyste měli jistotu, že nemáte problémy s používáním PowerShellu nebo rozšíření PowerShellu ve VS Code, musíte správně nakonfigurovat nastavení VS Code a PowerShellu.

Běžné příčiny problémů s kódováním

K problémům s kódováním dochází, když kódování VS Code nebo soubor skriptu neodpovídá očekávanému kódování PowerShellu. PowerShell nemůže automaticky určit kódování souborů.

S větší pravděpodobností máte problémy s kódováním, když používáte znaky, které nejsou v 7bitové znakové sadě ASCII. Příklad:

  • Rozšířené neznaméčkové znaky, jako jsou em-dash (), mezera bez přerušení ( ) nebo levá uvozovka (")
  • Zvýrazněné znaky latinky (É, ü)
  • Jiné než latinky, jako je cyrilice (Д, Ц)
  • Znaky CJK (, , )

Mezi běžné důvody problémů s kódováním patří:

  • Kódování VS Code a PowerShellu se nezměnily z výchozích hodnot. Pro PowerShell 5.1 a níže se výchozí kódování liší od kódu VS Code.
  • Jiný editor soubor otevřel a přepsal v novém kódování. K tomu často dochází u ISE.
  • Soubor je vrácen do správy zdrojového kódu v kódování, které se liší od toho, co očekává VS Code nebo PowerShell. K tomu může dojít, když spolupracovníci používají editory s různými konfiguracemi kódování.

Jak zjistit, kdy máte problémy s kódováním

Často se chyby kódování vyskytují jako parsování chyb ve skriptech. Pokud ve skriptu najdete podivné sekvence znaků, může to být problém. V následujícím příkladu se jako znaky â€"zobrazí pomlčka () :

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 â&euro;"From $from â&euro;"To $recipient1 â&euro;"Subject $subject  ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Send-MailMessage], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.SendMailMessage

K tomuto problému dochází, protože VS Code kóduje znak v UTF-8 jako bajty 0xE2 0x80 0x93. Když jsou tyto bajty dekódovány jako Windows-1252, jsou interpretovány jako znaky â&euro;".

Mezi podivné sekvence znaků, které se můžou zobrazit, patří:

  • â&euro;" Namísto
  • â&euro;" Namísto
  • Ä2 Namísto Ä
  •   místo (nerušil prostor)
  • Ã&copy; Namísto é

Tento praktický odkaz uvádí běžné vzory, které označují problém s kódováním UTF-8/Windows-1252.

Jak rozšíření PowerShellu ve VS Code komunikuje s kódováním

Rozšíření PowerShellu komunikuje se skripty několika způsoby:

  1. Při úpravách skriptů ve VS Code se obsah odešle do rozšíření VS Code. Protokol jazykového serveru vyžaduje, aby se tento obsah přenášel v UTF-8. Proto není možné, aby rozšíření získalo nesprávné kódování.
  2. Když se skripty spustí přímo v integrované konzole, načtou se ze souboru přímo pomocí PowerShellu. Pokud se kódování PowerShellu liší od kódu VS Code, může se tady něco pokazit.
  3. Když skript, který je otevřen ve VS Code odkazuje na jiný skript, který není otevřen ve VS Code, rozšíření se vrátí k načtení obsahu daného skriptu ze systému souborů. Rozšíření PowerShellu ve výchozím nastavení používá kódování UTF-8, ale k výběru správného kódování používá znaménko pořadí bajtů nebo boM.

K problému dochází v případě, že za předpokladu kódování formátů bom-less (například UTF-8 bez BOM a Windows-1252). Výchozí nastavení rozšíření PowerShellu je UTF-8. Rozšíření nemůže změnit nastavení kódování VS Code. Další informace najdete v tématu problém č. 824.

Výběr správného kódování

Různé systémy a aplikace můžou používat různé kódování:

  • V .NET Standard, na webu a na linuxovém světě je UTF-8 nyní dominantní kódování.
  • Mnoho aplikací rozhraní .NET Framework používá UTF-16. Z historických důvodů se tomu někdy říká "Unicode", termín, který teď odkazuje na obecný standard , který zahrnuje UTF-8 i UTF-16.
  • Ve Windows mnoho nativních aplikací, které predate Unicode ve výchozím nastavení používají Windows-1252.

Kódování Unicode mají také koncept značky bajtů (BOM). K boM dochází na začátku textu, aby dekodér, který kóduje text, který používá. U kódování s více bajty označuje boM také koncovost kódování. Kusovníky jsou navržené tak, aby byly bajty, které se zřídka vyskytují v textu bez kódování Unicode, což umožňuje rozumný odhad, že text je Unicode, když je k dispozici kusovník.

Kusovníky jsou volitelné a jejich přijetí není v linuxovém světě tak oblíbené, protože spolehlivé konvence UTF-8 se používá všude. Většina linuxových aplikací předpokládá, že textový vstup je kódován v UTF-8. I když mnoho linuxových aplikací rozpozná a správně zpracuje kusovník, číslo ne, což vede k artefaktům v textu manipulovaných s těmito aplikacemi.

Proto:

  • Pokud pracujete primárně s aplikacemi pro Windows a Windows PowerShell, měli byste preferovat kódování, jako je UTF-8 s BOM nebo UTF-16.
  • Pokud pracujete na různých platformách, měli byste upřednostnit UTF-8 s kusovníkem.
  • Pokud pracujete hlavně v kontextech přidružených k Linuxu, měli byste preferovat UTF-8 bez BOM.
  • Windows-1252 a latin-1 jsou v podstatě starší kódování, kterým byste se měli vyhnout, pokud je to možné. Některé starší aplikace pro Windows ale můžou záviset na nich.
  • Je také třeba poznamenat, že podepisování skriptů je závislé na kódování, což znamená, že změna kódování na podepsaném skriptu bude vyžadovat rezignování.

Konfigurace nástroje VS Code

Výchozí kódování VS Code je UTF-8 bez BOM.

Pokud chcete nastavit kódování VS Code, přejděte do nastavení VS Code (Ctrl+) a nastavte "files.encoding" nastavení:

"files.encoding": "utf8bom"

Mezi možné hodnoty patří:

  • utf8: [UTF-8] bez kusovníku
  • utf8bom: [UTF-8] s kusovníkem
  • utf16le: Malý endian [UTF-16]
  • utf16be: Big endian [UTF-16]
  • windows1252: [Windows-1252]

V zobrazení grafického uživatelského rozhraní byste měli získat rozevírací seznam nebo jeho dokončení v zobrazení JSON.

Pokud je to možné, můžete také přidat následující kód pro automatické rozpoznávání:

"files.autoGuessEncoding": true

Pokud nechcete, aby tato nastavení ovlivnila všechny typy souborů, nástroj VS Code také umožňuje konfigurace jednotlivých jazyků. Vytvořte nastavení specifické pro jazyk tak, že vložíte nastavení do [<language-name>] pole. Příklad:

"[powershell]": {
    "files.encoding": "utf8bom",
    "files.autoGuessEncoding": true
}

Můžete také zvážit instalaci nástroje Gremlins tracker pro Visual Studio Code. Toto rozšíření odhalí určité znaky Unicode, které jsou snadno poškozené, protože jsou neviditelné nebo vypadají jako jiné normální znaky.

Konfigurace PowerShellu

Výchozí kódování PowerShellu se liší v závislosti na verzi:

  • V PowerShellu 6+ je výchozí kódování UTF-8 bez BOM na všech platformách.
  • Ve Windows PowerShell je výchozí kódování obvykle Windows-1252, rozšíření latin-1, označované také jako ISO 8859-1.

V PowerShellu 5 a novějších najdete výchozí kódování pomocí tohoto:

[psobject].Assembly.GetTypes() | Where-Object { $_.Name -eq 'ClrFacade'} |
  ForEach-Object {
    $_.GetMethod('GetDefaultEncoding', [System.Reflection.BindingFlags]'nonpublic,static').Invoke($null, @())
  }

Pomocí následujícího skriptu můžete určit, jaké kódování relace PowerShellu odvodí skript bez kusovníku.

$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
}

PowerShell je možné nakonfigurovat tak, aby používal dané kódování obecněji pomocí nastavení profilu. Viz následující články:

PowerShell není možné vynutit použití konkrétního kódování vstupu. PowerShell 5.1 a novější, který běží ve Windows s národním prostředím nastaveným na en-US, se ve výchozím nastavení nastaví na kódování Windows-1252, pokud neexistuje žádný kusovník. Jiné nastavení národního prostředí může používat jiné kódování. Abyste zajistili interoperabilitu, je nejlepší uložit skripty ve formátu Unicode pomocí kusovníku.

Důležité

Všechny další nástroje, které máte, mohou být ovlivněny vašimi volbami kódování nebo opětovným kódováním skriptů do jiného kódování.

Existující skripty

Skripty, které už jsou v systému souborů, možná bude potřeba znovu zakódovat do nového zvoleného kódování. Na dolním panelu VS Code uvidíte popisek UTF-8. Kliknutím otevřete panel akcí a vyberte Uložit s kódováním. Teď můžete vybrat nové kódování pro tento soubor. Úplné pokyny najdete v kódování VS Code .

Pokud potřebujete znovu zakódovat více souborů, můžete použít následující skript:

Get-ChildItem *.ps1 -Recurse | ForEach-Object {
    $content = Get-Content -Path $_
    Set-Content -Path $_.Fullname -Value $content -Encoding UTF8 -PassThru -Force
}

Integrované skriptovací prostředí PowerShellu (ISE)

Pokud také upravujete skripty pomocí prostředí PowerShell ISE, musíte tam synchronizovat nastavení kódování.

ISE by měl respektovat bom, ale je také možné použít reflexi k nastavení kódování. Všimněte si, že by to nebylo zachováno mezi spuštěními.

Software pro správu zdrojového kódu

Některé nástroje pro správu zdrojového kódu, jako je git, ignorují kódování; Git jen sleduje bajty. Jiné, například Azure DevOps nebo Mercurial, nemusí. Dokonce i některé nástroje založené na Gitu spoléhají na dekódování textu.

V takovém případě se ujistěte, že:

  • Nakonfigurujte kódování textu ve správě zdrojového kódu tak, aby odpovídalo konfiguraci nástroje VS Code.
  • Ujistěte se, že jsou všechny soubory v příslušném kódování vráceny se správou zdrojového kódu.
  • Dávejte pozor na změny kódování přijaté prostřednictvím správy zdrojového kódu. Klíčové znaménko je rozdíl, který označuje změny, ale tam, kde se zdá, že se nic nezměnilo (protože bajty mají, ale znaky nemají).

Prostředí spolupracovníků

Nad konfigurací správy zdrojového kódu se ujistěte, že vaši spolupracovníci na všech sdílených souborech nemají nastavení, která přepisují kódování pomocí souborů PowerShellu pro opětovné kódování.

Další programy

Jakýkoli jiný program, který čte nebo zapisuje skript PowerShellu, ho může znovu zakódovat.

Tady je několik příkladů:

  • Pomocí schránky zkopírujte a vložte skript. To je běžné ve scénářích, jako je:
    • Kopírování skriptu do virtuálního počítače
    • Kopírování skriptu z e-mailu nebo webové stránky
    • Kopírování skriptu do nebo z dokumentu Microsoft Wordu nebo PowerPointu
  • Jiné textové editory, například:
    • Poznámkový blok
    • vim
    • Jakýkoli jiný editor skriptů PowerShellu
  • Nástroje pro úpravy textu, například:
    • Get-Content/Set-Content/Out-File
    • Operátory přesměrování PowerShellu, jako > jsou a >>
    • sed/awk
  • Programy pro přenos souborů, například:
    • Webový prohlížeč při stahování skriptů
    • Sdílená složka

Některé z těchto nástrojů se zabývají bajty místo textu, ale jiné nabízejí konfigurace kódování. V takových případech, kdy potřebujete nakonfigurovat kódování, musíte ho nastavit stejně jako kódování editoru, abyste zabránili problémům.

Další zdroje informací o kódování v PowerShellu

Existuje několik dalších pěkných příspěvků o kódování a konfiguraci kódování v PowerShellu, které stojí za přečtení: