Informatie over bestandscodering in VS Code en PowerShell

Wanneer u VS Code gebruikt om PowerShell-scripts te maken en te bewerken, is het belangrijk dat uw bestanden worden opgeslagen met de juiste tekencoderingsindeling.

Wat is bestandscodering en waarom is het belangrijk?

VS Code beheert de interface tussen een mens die tekenreeksen met tekens invoert in een buffer en lees-/schrijfblokken van bytes naar het bestandssysteem. Wanneer VS Code een bestand opslaat, wordt een tekstcodering gebruikt om te bepalen welke bytes elk teken wordt. Zie about_Character_Encoding voor meer informatie.

Als PowerShell een script uitvoert, moeten de bytes in een bestand worden geconverteerd naar tekens om het bestand te reconstrueren in een PowerShell-programma. Omdat VS Code het bestand schrijft en PowerShell het bestand leest, moeten ze hetzelfde coderingssysteem gebruiken. Dit proces voor het parseren van een PowerShell-script gaat: bytes -tekens ->tokens ->>abstracte syntaxisstructuur ->uitvoering.

Vs Code en PowerShell worden geïnstalleerd met een verstandige standaardcoderingsconfiguratie. De standaardcodering die door PowerShell wordt gebruikt, is echter gewijzigd met de versie van PowerShell 6. Om ervoor te zorgen dat u geen problemen ondervindt met het gebruik van PowerShell of de PowerShell-extensie in VS Code, moet u uw VS Code- en PowerShell-instellingen correct configureren.

Veelvoorkomende oorzaken van coderingsproblemen

Er treden coderingsproblemen op wanneer de codering van VS Code of uw scriptbestand niet overeenkomt met de verwachte codering van PowerShell. PowerShell kan de bestandscodering niet automatisch bepalen.

Het is waarschijnlijker dat u coderingsproblemen ondervindt wanneer u tekens gebruikt die niet in de 7-bits ASCII-tekenset staan. Bijvoorbeeld:

  • Uitgebreide niet-lettertekens, zoals em-dash (), niet-brekende spatie ( ) of dubbele aanhalingstekens links (")
  • Latijnse tekens met accenten (É, ü)
  • Niet-Latijnse tekens zoals Cyrillisch (Д, Ц)
  • CJK-tekens (, , )

Veelvoorkomende redenen voor coderingsproblemen zijn:

  • De coderingen van VS Code en PowerShell zijn niet gewijzigd van de standaardinstellingen. Voor PowerShell 5.1 en lager verschilt de standaardcodering van VS Code.
  • Een andere editor heeft het bestand geopend en overschreven in een nieuwe codering. Dit gebeurt vaak met de ISE.
  • Het bestand wordt ingecheckt in broncodebeheer in een codering die verschilt van wat VS Code of PowerShell verwacht. Dit kan gebeuren wanneer medewerkers editors gebruiken met verschillende coderingsconfiguraties.

Hoe u kunt zien wanneer u coderingsproblemen hebt

Vaak worden coderingsfouten weergegeven als parseringsfouten in scripts. Als u vreemde tekenreeksen in uw script vindt, kan dit het probleem zijn. In het onderstaande voorbeeld wordt een en-dash () weergegeven als de tekens â€":

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

Dit probleem treedt op omdat VS Code het teken in UTF-8 codeert als de bytes 0xE2 0x80 0x93. Wanneer deze bytes worden gedecodeerd als Windows-1252, worden ze geïnterpreteerd als de tekens â&euro;".

Enkele vreemde tekenreeksen die u mogelijk ziet, zijn:

  • â&euro;" In plaats van
  • â&euro;" In plaats van
  • Ä2 In plaats van Ä
  • Â in plaats van   (een niet-brekende spatie)
  • Ã&copy; In plaats van é

Deze handige referentie bevat de algemene patronen die duiden op een UTF-8/Windows-1252-coderingsprobleem.

Hoe de PowerShell-extensie in VS Code communiceert met coderingen

De PowerShell-extensie communiceert op verschillende manieren met scripts:

  1. Wanneer scripts worden bewerkt in VS Code, wordt de inhoud door VS Code naar de extensie verzonden. Het Language Server Protocol vereist dat deze inhoud wordt overgedragen in UTF-8. Daarom is het niet mogelijk dat de extensie de verkeerde codering krijgt.
  2. Wanneer scripts rechtstreeks in de geïntegreerde console worden uitgevoerd, worden ze rechtstreeks uit het bestand gelezen door PowerShell. Als de codering van PowerShell verschilt van vs Code, kan er hier iets misgaan.
  3. Wanneer een script dat is geopend in VS Code verwijst naar een ander script dat niet is geopend in VS Code, valt de extensie terug op het laden van de inhoud van dat script vanuit het bestandssysteem. De PowerShell-extensie is standaard ingesteld op UTF-8-codering, maar maakt gebruik van byte-ordermarkeringen of bomdetectie om de juiste codering te selecteren.

Het probleem treedt op bij het aannemen van de codering van BOM-less-indelingen (zoals UTF-8 zonder BOM en Windows-1252). De PowerShell-extensie wordt standaard ingesteld op UTF-8. De extensie kan de coderingsinstellingen van VS Code niet wijzigen. Zie probleem 824 voor meer informatie.

De juiste codering kiezen

Verschillende systemen en toepassingen kunnen verschillende coderingen gebruiken:

  • In .NET Standard, op internet en in de Linux-wereld, is UTF-8 nu de dominante codering.
  • Veel .NET Framework toepassingen gebruiken UTF-16. Om historische redenen wordt dit ook wel Unicode genoemd, een term die nu verwijst naar een brede standaard met zowel UTF-8 als UTF-16.
  • In Windows blijven veel systeemeigen toepassingen waarop Unicode voorafgaat standaard Windows-1252 gebruiken.

Unicode-coderingen hebben ook het concept van een byte-ordermarkering (BOM). BOM's vinden aan het begin van de tekst plaats om een decoder te laten weten welke codering van de tekst wordt gebruikt. Voor coderingen met meerdere bytes geeft de BOM ook de endianiteit van de codering aan. BOM's zijn ontworpen om bytes te zijn die zelden voorkomen in niet-Unicode-tekst, waardoor een redelijke schatting wordt gemaakt dat tekst Unicode is wanneer een stuklijst aanwezig is.

BOM's zijn optioneel en hun acceptatie is niet zo populair in de Linux-wereld, omdat overal een betrouwbare conventie van UTF-8 wordt gebruikt. In de meeste Linux-toepassingen wordt ervan uitgegaan dat tekstinvoer is gecodeerd in UTF-8. Hoewel veel Linux-toepassingen een stuklijst herkennen en correct verwerken, leidt dit niet tot artefacten in tekst die met deze toepassingen worden gemanipuleerd.

Daarom:

  • Als u voornamelijk werkt met Windows-toepassingen en Windows PowerShell, moet u de voorkeur geven aan een codering zoals UTF-8 met BOM of UTF-16.
  • Als u op verschillende platforms werkt, moet u de voorkeur geven aan UTF-8 met BOM.
  • Als u voornamelijk werkt in aan Linux gekoppelde contexten, moet u de voorkeur geven aan UTF-8 zonder stuklijst.
  • Windows-1252 en latin-1 zijn in wezen verouderde coderingen die u indien mogelijk moet vermijden. Sommige oudere Windows-toepassingen kunnen echter afhankelijk zijn van deze toepassingen.
  • Het is ook de moeite waard om te vermelden dat ondertekening van scripts afhankelijk is van codering, wat betekent dat een wijziging van codering voor een ondertekend script moet worden ontslagen.

VS Code configureren

De standaardcodering van VS Code is UTF-8 zonder stuklijst.

Als u de codering van VS Code wilt instellen, gaat u naar de VS Code-instellingen (Ctrl+,) en stelt u de "files.encoding" instelling in:

"files.encoding": "utf8bom"

Enkele mogelijke waarden zijn:

  • utf8: [UTF-8] zonder stuklijst
  • utf8bom: [UTF-8] met BOM
  • utf16le: Little endian [UTF-16]
  • utf16be: Big endian [UTF-16]
  • windows1252: [Windows-1252]

U krijgt een vervolgkeuzelijst voor dit in de GUI-weergave of voltooiingen voor deze in de JSON-weergave.

U kunt indien mogelijk ook het volgende toevoegen aan automatisch detecteren van codering:

"files.autoGuessEncoding": true

Als u niet wilt dat deze instellingen van invloed zijn op alle bestandstypen, staat VS Code ook configuraties per taal toe. Maak een taalspecifieke instelling door instellingen in een [<language-name>] veld te plaatsen. Bijvoorbeeld:

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

U kunt ook overwegen om de Gremlins-tracker voor Visual Studio Code te installeren. Deze extensie toont bepaalde Unicode-tekens die gemakkelijk beschadigd zijn omdat ze onzichtbaar zijn of eruitzien als andere normale tekens.

PowerShell configureren

De standaardcodering van PowerShell varieert afhankelijk van de versie:

  • In PowerShell 6+ is de standaardcodering UTF-8 zonder stuklijst op alle platforms.
  • In Windows PowerShell is de standaardcodering meestal Windows-1252, een uitbreiding van latin-1, ook wel bekend als ISO 8859-1.

In PowerShell 5+ vindt u hier uw standaardcodering:

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

Het volgende script kan worden gebruikt om te bepalen welke codering van uw PowerShell-sessie wordt afgeleid voor een script zonder een stuklijst.

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

Het is mogelijk om PowerShell te configureren voor het gebruik van een bepaalde codering in het algemeen met behulp van profielinstellingen. Zie de volgende artikelen:

Het is niet mogelijk om PowerShell te dwingen om een specifieke invoercodering te gebruiken. PowerShell 5.1 en lager, uitgevoerd op Windows met de landinstelling ingesteld op en-US, wordt standaard ingesteld op Windows-1252-codering wanneer er geen bom is. Andere landinstellingen kunnen een andere codering gebruiken. Om de interoperabiliteit te garanderen, kunt u scripts het beste opslaan in een Unicode-indeling met een stuklijst.

Belangrijk

Andere hulpprogramma's die u hebt die powerShell-scripts aanraken, kunnen worden beïnvloed door uw coderingsopties of uw scripts opnieuw coderen naar een andere codering.

Bestaande scripts

Scripts die al op het bestandssysteem staan, moeten mogelijk opnieuw worden gecodeerd naar de nieuwe gekozen codering. In de onderste balk van VS Code ziet u het label UTF-8. Klik erop om de actiebalk te openen en selecteer Opslaan met codering. U kunt nu een nieuwe codering voor dat bestand kiezen. Zie de codering van VS Code voor volledige instructies.

Als u meerdere bestanden opnieuw moet coderen, kunt u het volgende script gebruiken:

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

De Geïntegreerde PowerShell-scriptomgeving (ISE)

Als u ook scripts bewerkt met powerShell ISE, moet u daar uw coderingsinstellingen synchroniseren.

De ISE moet een BOM respecteren, maar het is ook mogelijk om reflectie te gebruiken om de codering in te stellen. Houd er rekening mee dat dit niet tussen start-ups zou blijven bestaan.

Broncodebeheersoftware

Sommige hulpprogramma's voor broncodebeheer, zoals Git, negeren coderingen; Git houdt alleen de bytes bij. Andere, zoals Azure DevOps of Mercurial, kunnen dat niet. Zelfs sommige git-hulpprogramma's zijn afhankelijk van het decoderen van tekst.

Als dit het geval is, controleert u het volgende:

  • Configureer de tekstcodering in uw broncodebeheer zodat deze overeenkomt met uw VS Code-configuratie.
  • Zorg ervoor dat al uw bestanden zijn ingecheckt bij broncodebeheer in de relevante codering.
  • Wees voorzichtig met wijzigingen in de codering die via broncodebeheer zijn ontvangen. Een sleutelteken hiervan is een diff die wijzigingen aangeeft, maar waarbij niets lijkt te zijn gewijzigd (omdat bytes maar tekens niet hebben).

Omgevingen van samenwerkers

Zorg er naast het configureren van broncodebeheer voor dat uw samenwerkers voor bestanden die u deelt, geen instellingen hebben die uw codering overschrijven door PowerShell-bestanden opnieuw te coderen.

Andere programma's

Elk ander programma dat een PowerShell-script leest of schrijft, kan het opnieuw coderen.

Een aantal voorbeelden:

  • Het Klembord gebruiken om een script te kopiëren en plakken. Dit is gebruikelijk in scenario's zoals:
    • Een script kopiëren naar een VM
    • Een script uit een e-mailbericht of webpagina kopiëren
    • Een script kopiëren naar of uit een Microsoft Word- of PowerPoint-document
  • Andere teksteditors, zoals:
    • Kladblok
    • vim
    • Andere PowerShell-scripteditor
  • Hulpprogramma's voor tekstbewerking, zoals:
    • Get-Content/Set-Content/Out-File
    • PowerShell-omleidingsoperators zoals > en >>
    • sed/awk
  • Programma's voor bestandsoverdracht, zoals:
    • Een webbrowser bij het downloaden van scripts
    • Een bestandsshare

Sommige van deze hulpprogramma's hebben betrekking op bytes in plaats van tekst, maar andere bieden coderingsconfiguraties. In gevallen waarin u een codering moet configureren, moet u deze hetzelfde maken als de codering van uw editor om problemen te voorkomen.

Andere resources over codering in PowerShell

Er zijn enkele andere leuke berichten over codering en het configureren van codering in PowerShell die een lees waard zijn: