Informazioni sulla codifica di file in VS Code e PowerShell

Quando si usa VS Code per creare e modificare script di PowerShell, è importante salvare i file usando il formato di codifica dei caratteri corretto.

Che cos'è la codifica dei file e perché è importante?

VS Code gestisce l'interfaccia tra una persona che immette stringhe di caratteri in un buffer e i blocchi di lettura/scrittura di byte nel File system. Durante il salvataggio di un file da parte di VS Code, viene usata una codifica del testo per definire i byte in cui viene convertito ogni carattere. Per altre informazioni, vedere about_Character_Encoding.

Analogamente, quando PowerShell esegue uno script deve convertire i byte di un file in caratteri per ricostruire il file in un programma di PowerShell. Poiché VS Code scrive il file e PowerShell legge il file, devono usare lo stesso sistema di codifica. Questo processo di analisi di uno script di PowerShell è: byte ->characters ->tokens ->abstract syntax tree ->execution.

Sia VS Code che PowerShell vengono installati con una configurazione di codifica predefinita appropriata. Tuttavia, la codifica predefinita usata da PowerShell è cambiata con la versione di PowerShell 6. Per assicurarsi di non avere problemi usando PowerShell o l'estensione di PowerShell in VS Code, è necessario configurare le impostazioni di VS Code e di PowerShell in modo corretto.

Cause più comuni dei problemi di codifica

I problemi di codifica si verificano quando la codifica di VS Code o il file di script non corrisponde alla codifica prevista di PowerShell. Non è possibile per PowerShell determinare automaticamente la codifica del file.

I problemi di codifica si verificano con maggiore probabilità quando si usano caratteri non del set di caratteri ASCII a 7 bit. Ad esempio:

  • Caratteri non letterali estesi, ad esempio la lineetta (), lo spazio unificatore ( ) o le virgolette inglesi aperte (")
  • Caratteri latini accentati (É, ü)
  • Caratteri non latini, ad esempio cirillico (Д, Ц)
  • Caratteri CJK (, , )

I motivi comuni per i problemi di codifica sono:

  • Le codifiche di VS Code e PowerShell non sono state modificate rispetto alle impostazioni predefinite. Per PowerShell 5.1 e versioni precedenti la codifica predefinita è diversa da quella di VS Code.
  • Un altro editor ha aperto e sovrascritto il file in una nuova codifica. Ciò si verifica spesso con ISE.
  • Il file viene archiviato nel controllo del codice sorgente in una codifica diversa da quella prevista da VS Code o PowerShell. Questa situazione può verificarsi quando i collaboratori usano editor con diverse configurazioni di codifica.

Come sapere quando sono presenti problemi di codifica

Spesso gli errori di codifica si presentano come errori di analisi negli script. Se si rilevano strane sequenze di caratteri nello script, questo può essere il problema. Nell'esempio seguente un trattino () viene visualizzato come i caratteri â€":

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

Questo problema si verifica perché VS Code codifica il carattere in formato UTF-8 come i byte 0xE2 0x80 0x93. Quando questi byte vengono decodificati come Windows-1252, vengono interpretati come caratteri â&euro;".

Di seguito sono riportate alcune sequenze di caratteri insolite che potrebbero essere visualizzate:

  • â&euro;" invece di (un trattino en-dash)
  • â&euro;" invece di (un trattino em-dash)
  • Ä2 invece di Ä
  • Â invece di   (uno spazio non di rilievo)
  • Ã&copy; invece di é

In questo utile riferimento sono elencati i modelli che più spesso indicano un problema di codifica UTF-8 o Windows-1252.

Modalità di interazione con le codifiche dell'estensione di PowerShell in VS Code

L'estensione di PowerShell interagisce con gli script in diversi modi:

  1. Quando gli script vengono modificati in VS Code, i contenuti vengono inviati da VS Code all'estensione. Il protocollo di server di linguaggio impone che il contenuto venga trasferito in UTF-8. Non è quindi possibile che l'estensione ottenga la codifica errata.
  2. Quando gli script vengono eseguiti direttamente nella console integrata, vengono letti da PowerShell direttamente dal file. Se la codifica di PowerShell è diversa da quella di VS Code, si può verificare un problema.
  3. Quando uno script aperto in VS Code fa riferimento a un altro script che non è aperto in VS Code, l'estensione esegue il fallback al caricamento del contenuto dello script dal file system. L'estensione di PowerShell per impostazione predefinita usa la codifica UTF-8, ma usa il rilevamento byte order mark, o BOM, per selezionare la codifica corretta.

Il problema si verifica quando si presuppone l'uso della codifica dei formati senza BOM, ad esempio UTF-8 senza BOM e Windows-1252. L'estensione di PowerShell usa UTF-8 come valore predefinito. L'estensione non può modificare le impostazioni di codifica di VS Code. Per altre informazioni, vedere il problema n. 824.

Scelta della codifica corretta

Applicazioni e sistemi diversi possono usare codifiche diverse:

  • In .NET Standard, sul Web e nel mondo Linux, UTF-8 è ora la codifica dominante.
  • Molte applicazioni .NET Framework usano la codifica UTF-16. Per motivi storici, a volte viene definita "Unicode", un termine che ora si riferisce a uno standard diffuso che include sia UTF-8 che UTF-16.
  • In Windows molte applicazioni native precedenti a Unicode continuano a usare Windows-1252 per impostazione predefinita.

Le codifiche Unicode prevedono inoltre il concetto di un byte order mark (BOM). I BOM si trovano all'inizio del testo per indicare a un decodificatore quale codifica sta usando il testo. Per le codifiche multibyte, il BOM indica anche l'ordine dei byte della codifica. I BOM sono progettati come byte che si verificano raramente nel testo non Unicode e la presenza di un BOM suggerisce che un testo è Unicode.

I BOM sono facoltativi e la loro adozione non è altrettanto diffusa nel mondo Linux perché viene usata ovunque una convenzione affidabile di UTF-8. La maggior parte delle applicazioni Linux presume che l'input di testo sia codificato in UTF-8. Anche se molte applicazioni Linux riconosceranno e gestiranno correttamente una distinta base, un numero non, causando artefatti nel testo manipolato con tali applicazioni.

Di conseguenza:

  • Se si lavora principalmente con le applicazioni Windows e Windows PowerShell, è preferibile la codifica UTF-8 con BOM o UTF-16.
  • Se si lavora su varie piattaforme, è preferibile usare UTF-8 con BOM.
  • Se si lavora principalmente in contesti associati a Linux, è preferibile usare UTF-8 senza BOM.
  • Windows-1252 e latin-1 sono essenzialmente le codifiche legacy che è opportuno evitare, se possibile. Tuttavia, alcune applicazioni Windows più datate possono dipendere da esse.
  • È anche importante notare che la firma degli script dipende dalla codifica, ovvero una modifica della codifica in uno script firmato richiede una nuova operazione di firma.

Configurazione di VS Code

La codifica predefinita di VS Code è UTF-8 senza BOM.

Per impostare la codifica di VS Code, accedere alle impostazioni di VS Code (CTRL+,) e specificare l'impostazione "files.encoding":

"files.encoding": "utf8bom"

Alcuni valori possibili sono:

  • utf8: [UTF-8] senza BOM
  • utf8bom: [UTF-8] con bom
  • utf16le: Little endian [UTF-16]
  • utf16be: Big endian [UTF-16]
  • windows1252: [Windows-1252]

Per questo oggetto è possibile ottenere un elenco a discesa nella visualizzazione GUI o i relativi completamenti nella visualizzazione JSON.

È anche possibile aggiungere quanto segue per rilevare automaticamente la codifica quando è possibile:

"files.autoGuessEncoding": true

Se si vuole evitare che queste impostazioni influiscano su tutti i tipi di file, VS Code consente anche di definire configurazioni diverse in base al linguaggio. Per creare un'impostazione specifica del linguaggio, inserire le impostazioni in un campo [<language-name>]. Ad esempio:

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

Può essere opportuno installare il tracker Gremlins per Visual Studio Code. Questa estensione rivela alcuni caratteri Unicode facilmente danneggiati perché sono invisibili o simili ad altri caratteri normali.

Configurazione di PowerShell

La codifica predefinita di PowerShell varia a seconda della versione:

  • In PowerShell 6 o versione successiva la codifica predefinita è UTF-8 senza BOM su tutte le piattaforme.
  • In Windows PowerShell la codifica predefinita è in genere Windows-1252, che è un'estensione di latin-1 (nota anche come ISO 8859-1).

In PowerShell 5 o versione successiva è possibile trovare la codifica predefinita in questo modo:

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

Lo script seguente può essere usato per determinare ciò che deduce la codifica della sessione di PowerShell per uno script senza 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
}

È possibile configurare PowerShell in modo che usi una codifica specifica più in generale usando le impostazioni del profilo. Fai riferimento ai seguenti articoli:

Non è possibile forzare PowerShell perché usi una codifica specifica per l'input. PowerShell 5.1 e versioni precedenti, in esecuzione in Windows con le impostazioni locali en-US, usano per impostazione predefinita la codifica Windows-1252 in assenza di BOM. Altre impostazioni locali potrebbero usare una codifica diversa. Per garantire l'interoperabilità, è preferibile salvare gli script in formato Unicode con BOM.

Importante

Le scelte in termini di codifica possono influire su eventuali altri strumenti che usano gli script di PowerShell o può essere opportuno codificare di nuovo gli script usando un'altra codifica.

Script esistenti

Può essere necessario ricodificare gli script già presenti nel file system in base alla nuova codifica scelta. Nella barra inferiore di VS Code viene visualizzata l'etichetta UTF-8. Fare clic sull'etichetta per aprire la barra delle azioni e selezionare Salva con codifica. È ora possibile selezionare una nuova codifica per il file. Vedere Codifica di VS Code per le istruzioni complete.

Se è necessario codificare di nuovo più file, è possibile usare lo script seguente:

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)

Se inoltre si modificano gli script con l'ISE di PowerShell, è necessario sincronizzare le impostazioni di codifica nell'ISE.

L'ISE deve rispettare un BOM, ma è anche possibile usare la reflection per impostare la codifica. Si noti che questa condizione non sarebbe persistente da un avvio all'altro.

Software di controllo del codice sorgente

Alcuni strumenti per il controllo del codice sorgente ignorano le codifiche, ad esempio GIT tiene traccia solo dei byte. Altri strumenti, ad esempio Azure DevOps o Mercurial, si comportano diversamente. Anche alcuni strumenti basati su GIT usano la decodifica del testo.

In questo caso verificare quanto segue:

  • Configurare la codifica del testo nel controllo del codice sorgente in modo che corrisponda alla configurazione di VS Code.
  • Verificare che tutti i file vengano sottoposti al controllo del codice sorgente con la codifica pertinente.
  • Fare attenzione alle modifiche della codifica segnalate dal controllo del codice sorgente. Un segno evidente è un diff che indica la presenza di modifiche quando apparentemente non ce ne sono (perché i byte sono cambiati e i caratteri no).

Ambienti dei collaboratori

Oltre a configurare il controllo del codice sorgente, verificare che i collaboratori che accedono ai file condivisi non usino impostazioni che sostituiscono la codifica in uso ricodificando i file di PowerShell.

Altri programmi

Qualsiasi altro programma che legge o scrive uno script di PowerShell può ricodificarlo.

Alcuni esempi sono:

  • Uso degli Appunti per copiare e incollare uno script. Questo è comune negli scenari come:
    • Copia di uno script in una macchina virtuale
    • Copia di uno script da un messaggio di posta elettronica o una pagina Web
    • Copia di uno script in o da un documento Microsoft Word o PowerPoint
  • Altri editor di testo, ad esempio:
    • Blocco note
    • vim
    • Qualsiasi altro editor di script di PowerShell
  • Utilità di modifica del testo, ad esempio:
    • Get-Content/Set-Content/Out-File
    • Operatori di reindirizzamento di PowerShell, ad esempio > e >>
    • sed/awk
  • Programmi di trasferimento file, ad esempio:
    • Un Web browser, durante il download degli script
    • Una condivisione file

Alcuni di questi strumenti gestiscono i byte anziché il testo, ma altri offrono configurazioni di codifica. Nei casi in cui è necessario configurare una codifica, tenere presente che deve essere la stessa codifica usata dall'editor per evitare problemi.

Altre risorse per la codifica in PowerShell

Esistono alcuni post interessanti sulla codifica e la configurazione della codifica in PowerShell che vale la pena leggere: