Förstå filkodning i VS Code och PowerShell

När du använder VS Code för att skapa och redigera PowerShell-skript är det viktigt att filerna sparas med rätt teckenkodningsformat.

Vad är filkodning och varför är det viktigt?

VS Code hanterar gränssnittet mellan en människa som anger teckensträngar i en buffert och läs-/skrivblock med byte till filsystemet. När VS Code sparar en fil används en textkodning för att bestämma vilka byte varje tecken blir. Mer information finns i about_Character_Encoding.

När PowerShell kör ett skript måste byte i en fil konverteras till tecken för att rekonstruera filen till ett PowerShell-program. Eftersom VS Code skriver filen och PowerShell läser filen måste de använda samma kodningssystem. Den här processen för att parsa ett PowerShell-skript går: bytes ->characters ->tokens ->abstract syntax tree ->execution.

Både VS Code och PowerShell installeras med en lämplig standardkodningskonfiguration. Standardkodningen som används av PowerShell har dock ändrats med versionen av PowerShell 6. För att säkerställa att du inte har några problem med att använda PowerShell eller PowerShell-tillägget i VS Code måste du konfigurera VS Code- och PowerShell-inställningarna korrekt.

Vanliga orsaker till kodningsproblem

Kodningsproblem uppstår när kodningen av VS Code eller skriptfilen inte matchar den förväntade kodningen av PowerShell. Det finns inget sätt för PowerShell att automatiskt fastställa filkodningen.

Det är mer troligt att du har kodningsproblem när du använder tecken som inte ingår i 7-bitarsuppsättningen för ASCII-tecken. Exempel:

  • Utökade icke-bokstavstecken som em-dash (), icke-blanksteg ( ) eller vänster dubbelt citattecken (")
  • Latinska accenttecken (É, ü)
  • Icke-latinska tecken som kyrilliska (Д, Ц)
  • CJK-tecken (, , )

Vanliga orsaker till kodningsproblem är:

  • Kodningarna för VS Code och PowerShell har inte ändrats från standardinställningarna. För PowerShell 5.1 och lägre skiljer sig standardkodningen från VS Code.
  • En annan redigerare har öppnat och skrivit över filen i en ny kodning. Detta sker ofta med ISE.
  • Filen checkas in i källkontrollen i en kodning som skiljer sig från vad VS Code eller PowerShell förväntar sig. Detta kan inträffa när medarbetare använder redigeringsprogram med olika kodningskonfigurationer.

Så här ser du när du har kodningsproblem

Ofta visas kodningsfel som parsningsfel i skript. Om du hittar konstiga teckensekvenser i skriptet kan det vara problemet. I exemplet nedan visas ett en-dash () som tecknen â€":

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

Det här problemet beror på att VS Code kodar tecknet i UTF-8 som byte.0xE2 0x80 0x93 När dessa byte avkodas som Windows-1252 tolkas de som tecknen â&euro;".

Några konstiga teckensekvenser som du kan se är:

  • â&euro;" Istället för
  • â&euro;" Istället för
  • Ä2 Istället för Ä
  • Â i stället   för (ett icke-blanksteg)
  • Ã&copy; Istället för é

Den här praktiska referensen visar de vanliga mönster som indikerar kodningsproblemet UTF-8/Windows-1252.

Så här interagerar PowerShell-tillägget i VS Code med kodningar

PowerShell-tillägget interagerar med skript på flera olika sätt:

  1. När skript redigeras i VS Code skickas innehållet av VS Code till tillägget. Language Server Protocol kräver att det här innehållet överförs i UTF-8. Därför är det inte möjligt för tillägget att få fel kodning.
  2. När skript körs direkt i den integrerade konsolen läss de direkt från filen av PowerShell. Om PowerShells kodning skiljer sig från VS Code kan något gå fel här.
  3. När ett skript som är öppet i VS Code refererar till ett annat skript som inte är öppet i VS Code, återgår tillägget till att läsa in skriptets innehåll från filsystemet. PowerShell-tillägget använder som standard UTF-8-kodning, men använder byteordningsmärke eller BOM-identifiering för att välja rätt kodning.

Problemet uppstår när du antar kodning av BOM-mindre format (till exempel UTF-8 utan BOM och Windows-1252). PowerShell-tillägget är som standard UTF-8. Tillägget kan inte ändra kodningsinställningarna för VS Code. Mer information finns i problem nr 824.

Välja rätt kodning

Olika system och program kan använda olika kodningar:

  • I .NET Standard, på webben och i Linux-världen är UTF-8 nu den dominerande kodningen.
  • Många .NET Framework program använder UTF-16. Av historiska skäl kallas detta ibland "Unicode", en term som nu refererar till en bred standard som innehåller både UTF-8 och UTF-16.
  • I Windows fortsätter många interna program som företablerar Unicode att använda Windows-1252 som standard.

Unicode-kodningar har också konceptet byte-order mark (BOM). BOM:er förekommer i början av texten för att tala om för en avkodare vilken kodning av texten som används. För multi-byte-kodningar indikerar BOM även kodningens endianitet . BOM:er är utformade för att vara byte som sällan förekommer i icke-Unicode-text, vilket ger en rimlig gissning om att texten är Unicode när det finns en BOM.

BOM:er är valfria och deras införande är inte lika populärt i Linux-världen eftersom en pålitlig konvention med UTF-8 används överallt. De flesta Linux-program förutsätter att textindata kodas i UTF-8. Även om många Linux-program känner igen och hanterar en BOM korrekt, gör inte ett tal det, vilket leder till artefakter i text som manipulerats med dessa program.

Därför:

  • Om du främst arbetar med Windows-program och Windows PowerShell bör du föredra en kodning som UTF-8 med BOM eller UTF-16.
  • Om du arbetar på olika plattformar bör du föredra UTF-8 med BOM.
  • Om du huvudsakligen arbetar i Linux-associerade kontexter bör du föredra UTF-8 utan BOM.
  • Windows-1252 och latin-1 är i stort sett äldre kodningar som du bör undvika om möjligt. Vissa äldre Windows-program kan dock vara beroende av dem.
  • Det är också värt att notera att skriptsignering är kodningsberoende, vilket innebär att en ändring av kodningen för ett signerat skript kräver att skriptet avgår.

Konfigurera VS Code

STANDARDkodningen i VS Code är UTF-8 utan BOM.

Om du vill ange VS Code-kodning går du till VS Code-inställningarna (Ctrl+) och anger "files.encoding" inställningen:

"files.encoding": "utf8bom"

Några möjliga värden är:

  • utf8: [UTF-8] utan BOM
  • utf8bom: [UTF-8] med BOM
  • utf16le: Little endian [UTF-16]
  • utf16be: Big endian [UTF-16]
  • windows1252: [Windows-1252]

Du bör få en listruta för detta i GUI-vyn eller slutföranden för den i JSON-vyn.

Du kan också lägga till följande för att automatiskt identifiera kodning när det är möjligt:

"files.autoGuessEncoding": true

Om du inte vill att de här inställningarna ska påverka alla filtyper tillåter VS Code även konfigurationer per språk. Skapa en språkspecifik inställning genom att placera inställningarna i ett [<language-name>] fält. Exempel:

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

Du kanske också vill överväga att installera Gremlins-spåraren för Visual Studio Code. Det här tillägget visar vissa Unicode-tecken som lätt skadas eftersom de är osynliga eller ser ut som andra normala tecken.

Konfigurera PowerShell

Standardkodningen för PowerShell varierar beroende på version:

  • I PowerShell 6+ är standardkodningen UTF-8 utan BOM på alla plattformar.
  • I Windows PowerShell är standardkodningen vanligtvis Windows-1252, en förlängning av latin-1, även kallat ISO 8859-1.

I PowerShell 5+ hittar du din standardkodning med följande:

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

Följande skript kan användas för att avgöra vilken kodning av PowerShell-sessionens slutsatsdragningar för ett skript utan 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
}

Det är möjligt att konfigurera PowerShell att använda en viss kodning mer allmänt med hjälp av profilinställningar. Se följande artiklar:

Det går inte att tvinga PowerShell att använda en specifik indatakodning. PowerShell 5.1 och lägre, som körs i Windows med nationella inställningar inställda på en-US, använder som standard Windows-1252-kodning när det inte finns någon BOM. Andra nationella inställningar kan använda en annan kodning. För att säkerställa samverkan är det bäst att spara skript i ett Unicode-format med en BOM.

Viktigt

Andra verktyg som du har som rör PowerShell-skript kan påverkas av dina kodningsalternativ eller koda om dina skript till en annan kodning.

Befintliga skript

Skript som redan finns i filsystemet kan behöva kodas om till din nya valda kodning. I det nedre fältet i VS Code visas etiketten UTF-8. Klicka på den för att öppna åtgärdsfältet och välj Spara med kodning. Nu kan du välja en ny kodning för filen. Fullständiga instruktioner finns i VS Code-kodningen .

Om du behöver koda om flera filer kan du använda följande skript:

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

PowerShell Integrated Scripting Environment (ISE)

Om du också redigerar skript med Hjälp av PowerShell ISE måste du synkronisera kodningsinställningarna där.

ISE bör respektera en strukturlista, men det är också möjligt att använda reflektion för att ange kodningen. Observera att detta inte skulle sparas mellan nystartade företag.

Programvara för källkontroll

Vissa verktyg för källkontroll, till exempel git, ignorerar kodningar. git spårar bara byte. Andra, till exempel Azure DevOps eller Mercurial, kanske inte gör det. Även vissa git-baserade verktyg förlitar sig på avkodning av text.

När så är fallet kontrollerar du att du:

  • Konfigurera textkodningen i källkontrollen så att den matchar VS Code-konfigurationen.
  • Se till att alla dina filer är incheckade i källkontrollen i relevant kodning.
  • Var försiktig med ändringar i kodningen som tas emot via källkontrollen. Ett viktigt tecken på detta är en diff som anger ändringar men där ingenting verkar ha ändrats (eftersom byte har men tecken inte har).

Medarbetares miljöer

Utöver att konfigurera källkontroll kontrollerar du att dina medarbetare på alla filer som du delar inte har inställningar som åsidosätter din kodning genom att koda om PowerShell-filer.

Andra program

Alla andra program som läser eller skriver ett PowerShell-skript kan koda om det.

Några exempel är:

  • Använda Urklipp för att kopiera och klistra in ett skript. Detta är vanligt i scenarier som:
    • Kopiera ett skript till en virtuell dator
    • Kopiera ett skript från ett e-postmeddelande eller en webbsida
    • Kopiera ett skript till eller från ett Microsoft Word- eller PowerPoint-dokument
  • Andra textredigerare, till exempel:
    • Anteckningar
    • vim
    • Andra PowerShell-skriptredigerare
  • Verktyg för textredigering, till exempel:
    • Get-Content/Set-Content/Out-File
    • PowerShell-omdirigeringsoperatorer som > och >>
    • sed/awk
  • Filöverföringsprogram, till exempel:
    • En webbläsare när skript laddas ned
    • En filresurs

Vissa av dessa verktyg hanterar byte i stället för text, men andra erbjuder kodningskonfigurationer. I de fall där du behöver konfigurera en kodning måste du göra den på samma sätt som redigeringskodningen för att förhindra problem.

Andra resurser om kodning i PowerShell

Det finns några andra bra inlägg om kodning och konfiguration av kodning i PowerShell som är värda att läsa: