Présentation de l’encodage de fichier dans VS Code et PowerShell

Quand vous utilisez VS Code pour créer et modifier des scripts PowerShell, il est important que vos fichiers soient enregistrés au format de codage de caractères approprié.

Qu’est-ce que l’encodage de fichier et pourquoi est-il important ?

VS Code gère l’interface entre un utilisateur qui entre des chaînes de caractères dans une mémoire tampon et la lecture/écriture de blocs d’octets dans le système de fichiers. Quand VS Code enregistre un fichier, il utilise un encodage de texte pour décider des octets attribués à chaque caractère. Pour plus d’informations, consultez about_Character_Encoding.

De même, quand PowerShell exécute un script, il doit convertir les octets d’un fichier en caractères afin de reconstruire le fichier dans un programme PowerShell. Comme VS Code écrit le fichier et que PowerShell le lit, ils doivent utiliser le même système d’encodage. Ce processus d’analyse d’un script PowerShell procède comme suit : octets ->caractères ->jetons ->arborescence de syntaxe abstraite ->exécution.

VS Code et PowerShell sont tous deux installés avec une configuration d’encodage par défaut adéquate. Toutefois, l’encodage par défaut utilisé par PowerShell a changé avec la publication de PowerShell 6. Pour être sûr de n’avoir aucun problème lors de l’utilisation de PowerShell ou de l’extension PowerShell dans VS Code, vous devez configurer vos paramètres VS Code et PowerShell correctement.

Causes courantes de problèmes d’encodage

Des problèmes de codage se produisent quand le codage de VS Code ou de votre fichier de script ne correspond pas au codage attendu de PowerShell. PowerShell ne dispose d’aucun moyen de déterminer automatiquement l’encodage du fichier.

Vous risquez davantage de rencontrer des problèmes d’encodage quand vous utilisez des caractères qui ne figurent pas dans le jeu de caractères ASCII sept bits. Par exemple :

  • les caractères non alphabétiques étendus comme le tiret cadratin (), l’espace insécable ( ) ou le guillemet double gauche (")
  • Les caractères latins accentués (É, ü)
  • Les caractères non latins tels que les caractères cyrilliques (Д, Ц)
  • Caractères CJC (, , )

Les causes courantes des problèmes d’encodage sont les suivantes :

  • Les codages de VS Code et de PowerShell n’ont pas changé par rapport à leurs valeurs par défaut. Pour PowerShell 5.1 et antérieur, l’encodage par défaut est différent de celui de VS Code.
  • Un autre éditeur a ouvert et remplacé le fichier dans un nouvel encodage. Cela se produit souvent avec l’environnement ISE.
  • Le fichier est archivé dans le contrôle de code source dans un autre codage que celui attendu par VS Code ou PowerShell. Cela peut se produire quand des collaborateurs utilisent des éditeurs avec différentes configurations d’encodage.

Comment savoir quand vous avez des problèmes d’encodage ?

Souvent, les erreurs d’encodage se présentent sous forme d’erreurs d’analyse dans les scripts. Si vous remarquez des séquences de caractères étranges dans votre script, il peut s’agir de ce type de problème. Dans l’exemple ci-dessous, les caractères â€" apparaissent à la place d’un tiret demi-cadratin () :

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

Ce problème se produit car VS Code encode le caractère en UTF-8 en tant qu’octets 0xE2 0x80 0x93. Quand ces octets sont décodés au format Windows-1252, ils sont interprétés en tant que caractères â&euro;".

Voici quelques séquences de caractères étranges susceptibles d’apparaître :

  • â&euro;" au lieu de (un tiret)
  • â&euro;" au lieu de (un trait d’union)
  • Ä2 au lieu de Ä
  • Â au lieu de   (un espace insécable)
  • Ã&copy; au lieu de é

Cette référence très pratique liste les modèles courants qui indiquent un problème d’encodage UTF-8/Windows-1252.

Interaction entre l’extension PowerShell dans VS Code et les encodages

L’extension PowerShell interagit avec les scripts de plusieurs façons :

  1. Quand les scripts sont modifiés dans VS Code, le contenu est envoyé par VS Code à l’extension. Le protocole de serveur de langage impose que ce contenu soit transféré en UTF-8. Il n’est donc pas possible que l’extension obtienne le mauvais codage.
  2. Quand les scripts sont exécutés directement dans la console intégrée, ils sont lus directement à partir du fichier par PowerShell. Si l’encodage de PowerShell est différent de celui de VS Code, les choses peuvent mal tourner.
  3. Quand un script ouvert dans VS Code référence un autre script qui n’est pas ouvert dans VS Code, l’extension charge le contenu de ce script à partir du système de fichiers. L’extension PowerShell utilise par défaut l’encodage UTF-8, mais elle utilise la détection de marque d’ordre d’octet pour sélectionner l’encodage correct.

Le problème se produit en cas d’encodage des formats sans marque d’ordre d’octet (comme UTF-8 sans marque d’ordre d’octet et Windows-1252). L’extension PowerShell utilise par défaut UTF-8. L’extension ne peut pas changer les paramètres de codage de VS Code. Pour plus d’informations, consultez le problème n°824.

Choix de l’encodage correct

Différents systèmes et applications peuvent utiliser différents encodages :

  • Dans .NET Standard, sur le web et dans le monde de Linux, UTF-8 est désormais l’encodage dominant.
  • De nombreuses applications .NET Framework utilisent UTF-16. Pour des raisons historiques, cet encodage est parfois appelé « Unicode », un terme qui fait aujourd’hui référence à une norme étendue incluant UTF-8 et UTF-16.
  • Sur Windows, de nombreuses applications natives qui sont antérieures à Unicode continuent à utiliser Windows-1252 par défaut.

Avec les encodages Unicode, il existe également le concept de marque d’ordre d’octet. Les marques d’ordre d’octet sont présentes au début, et elles indiquent au décodeur l’encodage utilisé par le texte. Pour les encodages multioctets, la marque d’ordre d’octet indique également le mode Endian de l’encodage. Les marques d’ordre d’octet sont conçues pour être des octets qui se produisent rarement dans le texte non-Unicode, ce qui permet d’estimer avec une raisonnable certitude que le texte est au format Unicode quand une marque d’ordre d’octet est présente.

Les marques d’ordre d’octet sont facultatives, et leur adoption n’est pas aussi populaire dans le monde de Linux, car une convention fiable d’UTF-8 est utilisée partout. La plupart des applications Linux partent du principe que l’entrée de texte est encodée en UTF-8. Bien que de nombreuses applications Linux reconnaissent et gèrent correctement une marque d’ordre d’octet, toutes ne le font pas, ce qui entraîne des artefacts dans le texte manipulé avec ces applications.

Par conséquent :

  • Si vous travaillez principalement avec des applications Windows et Windows PowerShell, vous devez privilégier un encodage comme UTF-8 avec marque d’ordre d’octet ou UTF-16.
  • Si vous travaillez sur plusieurs plateformes, vous devez privilégier UTF-8 avec marque d’ordre d’octet.
  • Si vous travaillez principalement dans des contextes associés à Linux, vous devez privilégier UTF-8 sans marque d’ordre d’octet.
  • Windows-1252 et latin-1 sont essentiellement des encodages hérités que vous devez éviter dans la mesure du possible. Toutefois, certaines applications Windows anciennes peuvent en dépendre.
  • Il convient également de noter que la signature de script est dépendante du codage, ce qui signifie qu’un changement de l’encodage sur un script signé nécessitera une nouvelle signature.

Configuration de VS Code

L’encodage par défaut de VS Code est UTF-8 sans marque d’ordre d’octet.

Pour définir Encodage de VS Code, accédez aux paramètres VS Code (Ctrl+,) et définissez le paramètre "files.encoding" :

"files.encoding": "utf8bom"

Voici quelques valeurs possibles :

  • utf8 : [UTF-8] sans marque d’ordre d’octet
  • utf8bom : [UTF-8] avec marque d’ordre d’octet
  • utf16le : mode Little Endian [UTF-16]
  • utf16be : mode Big Endian [UTF-16]
  • windows1252 : [Windows-1252]

Vous devez obtenir une liste déroulante pour cette option dans la vue de l’interface graphique utilisateur, ou une complétion dans la vue JSON.

Vous pouvez aussi ajouter les éléments suivants pour détecter automatiquement l’encodage quand c’est possible :

"files.autoGuessEncoding": true

Si vous ne souhaitez pas que ces paramètres affectent tous les types de fichiers, VS Code autorise également les configurations propres à un langage. Vous pouvez créer un paramètre propre au langage en plaçant des paramètres dans un champ [<language-name>]. Par exemple :

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

Vous pouvez également installer le tracker Gremlins pour Visual Studio Code. Cette extension révèle certains caractères Unicode qui sont facilement endommagés, car ils sont invisibles ou ressemblent à d’autres caractères normaux.

Configuration de PowerShell

L’encodage par défaut de PowerShell varie en fonction de la version :

  • Dans PowerShell 6 et ultérieur, l’encodage par défaut est UTF-8 sans marque d’ordre d’octet sur toutes les plateformes.
  • Dans Windows PowerShell, l’encodage par défaut est généralement Windows-1252 qui est une extension de latin-1, également appelé ISO 8859-1.

Dans PowerShell 5 et ultérieur, vous pouvez déterminer votre encodage comme suit :

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

Vous pouvez utiliser le script suivant pour déterminer quel encodage votre session PowerShell déduit pour un script sans marque d’ordre d’octet.

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

Il est possible de configurer PowerShell pour utiliser plus généralement un encodage donné à l’aide de paramètres de profil. Voir les articles suivants :

Il n’est pas possible de forcer PowerShell à utiliser un encodage d’entrée spécifique. PowerShell 5.1 et versions antérieures, s’exécutant sur Windows avec les paramètres régionaux définis sur en-US, utilise par défaut le codage Windows-1252 en l’absence de marque d’ordre d’octet. D’autres paramètres régionaux peuvent utiliser un codage différent. Pour garantir leur interopérabilité, il est préférable d’enregistrer les scripts dans un format Unicode avec une marque d’ordre d’octet.

Important

Tout autre outil qui traite des scripts PowerShell est susceptible d’être affecté par vos options d’encodage ou de ré-encoder vos scripts en un autre encodage.

Scripts existants

Vous devrez peut-être réencoder les scripts déjà présents sur le système de fichiers vers votre nouvel encodage choisi. Dans la barre inférieure de VS Code, vous verrez l’étiquette UTF-8. Cliquez dessus pour ouvrir la barre d’action et sélectionnez Enregistrer avec encodage. Vous pouvez maintenant choisir un nouvel encodage pour ce fichier. Pour des instructions complètes, consultez Encodage de VS Code.

Si vous avez besoin de ré-encoder plusieurs fichiers, vous pouvez utiliser le script suivant :

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

Environnement d'écriture de scripts intégré (ISE) de PowerShell

Si vous modifiez également des scripts à l’aide de PowerShell ISE, vous devez y synchroniser vos paramètres d’encodage.

L’environnement ISE doit respecter une marque d’ordre d’octet, mais il est également possible d’utiliser la réflexion pour définir l’encodage. Notez que cela ne serait pas conservé d’un démarrage à un autre.

Logiciels de contrôle de code source

Certains outils de contrôle de code source, tels que GIT, ignorent les encodages. GIT ne fait que suivre les octets. Ce n’est pas forcément le cas de tous, comme Azure DevOps ou Mercurial. Même certains outils GIT s’appuient sur le décodage du texte.

Quand c’est le cas, veillez à :

  • Configurer l’encodage du texte dans votre contrôle de code source pour qu’il corresponde à votre configuration de VS Code.
  • Vérifier que tous vos fichiers sont archivés dans le contrôle de code source dans l’encodage approprié.
  • Méfiez-vous des modifications apportées à l’encodage reçues par le biais du contrôle de code source. Un exemple courant est quand une comparaison indique des changements, mais que rien ne semble avoir été changé (car les octets ont changé, mais pas les caractères).

Environnements des collaborateurs

En plus de la configuration du contrôle de code source, veillez à ce que vos collaborateurs qui travaillent sur des fichiers que vous partagez n’aient pas de paramètres qui remplacent votre encodage en réencodant les fichiers PowerShell.

Autres programmes

Tout autre programme qui lit ou écrit un script PowerShell est susceptible de le ré-encoder.

Quelques exemples :

  • Utilisation du Presse-papiers pour copier et coller un script. C’est courant dans les scénarios suivants :
    • Copie d’un script dans une machine virtuelle
    • Copie d’un script à partir d’un e-mail ou d’une page web
    • Copie d’un script dans ou à partir d’un document Microsoft Word ou PowerPoint
  • Autres éditeurs de texte, tels que :
    • Bloc-notes
    • Vim
    • Tout autre éditeur de script PowerShell
  • Utilitaires d’édition de texte, tels que :
    • Get-Content/Set-Content/Out-File
    • Opérateurs de redirection PowerShell comme > et >>
    • sed/awk
  • Programmes de transfert de fichiers, tels que :
    • Un navigateur web, lors du téléchargement de scripts
    • Un partage de fichiers

Certains de ces outils traitent ses octets plutôt que du texte, mais d’autres offrent des configurations d’encodage. Dans les cas où vous devez configurer un encodage, vous devez faire en sorte qu’il soit identique à celui de votre éditeur afin d’éviter tout problème.

Autres ressources sur l’encodage dans PowerShell

Il existe quelques autres billets intéressants sur l’encodage et sa configuration dans PowerShell qui méritent une lecture :