Opis kodowania plików w programach VS Code i PowerShellUnderstanding file encoding in VS Code and PowerShell

W przypadku tworzenia i edytowania skryptów programu PowerShell przy użyciu VS Code należy pamiętać, że pliki są zapisywane przy użyciu poprawnego formatu kodowania znaków.When using VS Code to create and edit PowerShell scripts, it is important that your files are saved using the correct character encoding format.

Co to jest kodowanie plików i dlaczego są ważne?What is file encoding and why is it important?

VS Code zarządza interfejsem między człowiekem wprowadzającym ciągi znaków w buforze i odczytywaniem/zapisywaniem bloków bajtów do systemu plików.VS Code manages the interface between a human entering strings of characters into a buffer and reading/writing blocks of bytes to the filesystem. Gdy VS Code zapisuje plik, używa kodowania tekstu, aby zdecydować, jakie bajty są poszczególnymi znakami.When VS Code saves a file, it uses a text encoding to decide what bytes each character becomes. Aby uzyskać więcej informacji, zobacz about_Character_Encoding.For more information, see about_Character_Encoding.

Podobnie, gdy program PowerShell uruchamia skrypt, musi przekonwertować bajty w pliku na znaki, aby odtworzyć plik w programie PowerShell.Similarly, when PowerShell runs a script it must convert the bytes in a file to characters to reconstruct the file into a PowerShell program. Ponieważ VS Code zapisuje plik i program PowerShell odczytuje plik, muszą one korzystać z tego samego systemu kodowania.Since VS Code writes the file and PowerShell reads the file, they need to use the same encoding system. Ten proces analizowania skryptu programu PowerShell przebiega następująco: bajty -> characters -> tokeny -> wykonywanie drzewa składni abstrakcyjnej -> execution .This process of parsing a PowerShell script goes: bytes -> characters -> tokens -> abstract syntax tree -> execution .

Zarówno VS Code, jak i program PowerShell są instalowane z domyślną konfiguracją kodowania.Both VS Code and PowerShell are installed with a sensible default encoding configuration. Jednak domyślne kodowanie używane przez program PowerShell zostało zmienione wraz z wydaniem programu PowerShell Core (V6. x).However, the default encoding used by PowerShell has changed with the release of PowerShell Core (v6.x). Aby mieć pewność, że nie masz żadnych problemów przy użyciu programu PowerShell lub rozszerzenia programu PowerShell w VS Code, musisz odpowiednio skonfigurować ustawienia VS Code i programu PowerShell.To ensure you have no problems using PowerShell or the PowerShell extension in VS Code, you need to configure your VS Code and PowerShell settings properly.

Typowe przyczyny problemów z kodowaniemCommon causes of encoding issues

Występują problemy z kodowaniem, gdy kodowanie VS Code lub pliku skryptu nie jest zgodne z oczekiwanym kodowaniem programu PowerShell.Encoding problems occur when the encoding of VS Code or your script file does not match the expected encoding of PowerShell. Program PowerShell nie ma żadnego sposobu, aby automatycznie określić kodowanie pliku.There is no way for PowerShell to automatically determine the file encoding.

Jeśli używasz znaków, które nie znajdują się w 7-bitowym zestawie znaków ASCII, może wystąpić problem z kodowaniem.You're more likely to have encoding problems when you're using characters not in the 7-bit ASCII character set. Przykład:For example:

  • Rozszerzone znaki niebędące literami, takie jak pauza ( ), spacja nierozdzielająca ( ) lub podwójny cudzysłów ( " )Extended non-letter characters like em-dash (), non-breaking space ( ) or left double quotation mark (")
  • Znaki łacińskie z akcentem ( É , ü )Accented latin characters (É, ü)
  • Znaki inne niż łacińskie, takie jak cyrylica ( Д , Ц )Non-latin characters like Cyrillic (Д, Ц)
  • Znaki CJK ( , , )CJK characters (, , )

Typowe przyczyny problemów z kodowaniem:Common reasons for encoding issues are:

  • Kodowanie VS Code i programu PowerShell nie zostały zmienione z wartości domyślnych.The encodings of VS Code and PowerShell have not been changed from their defaults. Dla programu PowerShell 5,1 i poniżej domyślne kodowanie różni się od VS Code.For PowerShell 5.1 and below, the default encoding is different from VS Code's.
  • Inny edytor otworzył i nadpisał plik w nowym kodowaniu.Another editor has opened and overwritten the file in a new encoding. Zdarza się to często z ISE.This often happens with the ISE.
  • Plik jest sprawdzany w kontroli źródła w kodowaniu, które różni się od oczekiwanych VS Code lub programu PowerShell.The file is checked into source control in an encoding that is different from what VS Code or PowerShell expects. Może się tak zdarzyć, gdy współpracownicy używają edytorów z różnymi konfiguracjami kodowania.This can happen when collaborators use editors with different encoding configurations.

Jak powiedzieć, gdy występują problemy z kodowaniemHow to tell when you have encoding issues

Często są kodowane błędy występujące podczas analizowania błędów w skryptach.Often encoding errors present themselves as parse errors in scripts. Jeśli w skrypcie znajdziesz dziwne sekwencje znaków, może to być problem.If you find strange character sequences in your script, this can be the problem. W poniższym przykładzie znak EN-kreska ( ) pojawia się jako znaki â€" :In the example below, an en-dash () appears as the characters â€":

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

Ten problem występuje, ponieważ VS Code koduje znak w UTF-8 jako bajty 0xE2 0x80 0x93 .This problem occurs because VS Code encodes the character in UTF-8 as the bytes 0xE2 0x80 0x93. Gdy te bajty są zdekodowane jako Windows-1252, są interpretowane jako znaki â&euro;" .When these bytes are decoded as Windows-1252, they are interpreted as the characters â&euro;".

Niektóre dziwne sekwencje znaków, które mogą być widoczne:Some strange character sequences that you might see include:

  • â&euro;" Zamiast â&euro;" instead of
  • â&euro;" Zamiast â&euro;" instead of
  • Ä2 Zamiast ÄÄ2 instead of Ä
  • Â zamiast (miejsce niepowodujące podziału)Â instead of (a non-breaking space)
  • Ã&copy; Zamiast éÃ&copy; instead of é

Ta przydatna Dokumentacja zawiera listę wspólnych wzorców, które wskazują na problem z kodowaniem UTF-8/Windows-1252.This handy reference lists the common patterns that indicate a UTF-8/Windows-1252 encoding problem.

Jak rozszerzenie programu PowerShell w programie VS Code współdziała z kodowaniemHow the PowerShell extension in VS Code interacts with encodings

Rozszerzenie programu PowerShell współdziała ze skryptami na wiele sposobów:The PowerShell extension interacts with scripts in a number of ways:

  1. Gdy skrypty są edytowane w VS Code, zawartość jest wysyłana przez VS Code do rozszerzenia.When scripts are edited in VS Code, the contents are sent by VS Code to the extension. Protokół serwera języka określa, że ta zawartość jest transferowana w UTF-8.The Language Server Protocol mandates that this content is transferred in UTF-8. W związku z tym nie jest możliwe, aby rozszerzenie miało nieprawidłowe kodowanie.Therefore, it is not possible for the extension to get the wrong encoding.
  2. Gdy skrypty są wykonywane bezpośrednio w konsoli zintegrowanej, są one bezpośrednio odczytywane z pliku przez program PowerShell.When scripts are executed directly in the Integrated Console, they're read from the file by PowerShell directly. Jeśli kodowanie programu PowerShell różni się od VS Code, coś może być nieodpowiednie w tym miejscu.If PowerShell's encoding differs from VS Code's, something can go wrong here.
  3. Gdy skrypt otwarty w VS Code odwołuje się do innego skryptu, który nie jest otwarty w VS Code, rozszerzenie powraca do ładowania zawartości tego skryptu z systemu plików.When a script that is open in VS Code references another script that is not open in VS Code, the extension falls back to loading that script's content from the file system. Rozszerzenie programu PowerShell jest domyślnie zakodowane przy użyciu kodowania UTF-8, ale używa [znacznika kolejności bajtów][]lub BOM, aby wybrać prawidłowe kodowanie.The PowerShell extension defaults to UTF-8 encoding, but uses byte-order mark, or BOM, detection to select the correct encoding.

Ten problem występuje, gdy zakładasz kodowanie formatów bez BOM (na przykład UTF-8 i nie ma BOM ani Windows-1252).The problem occurs when assuming the encoding of BOM-less formats (like UTF-8 with no BOM and Windows-1252). Wartość domyślna rozszerzenia programu PowerShell to UTF-8.The PowerShell extension defaults to UTF-8. Rozszerzenie nie może zmienić ustawień kodowania VS Code.The extension cannot change VS Code's encoding settings. Aby uzyskać więcej informacji, zobacz temat #824 problemu.For more information, see issue #824.

Wybieranie odpowiedniego kodowaniaChoosing the right encoding

Różne systemy i aplikacje mogą używać różnych kodowań:Different systems and applications can use different encodings:

  • W .NET Standard, w sieci Web, a w świecie z systemem Linux, UTF-8 jest teraz rzeczywistym kodowaniem.In .NET Standard, on the web, and in the Linux world, UTF-8 is now the dominant encoding.
  • Wiele aplikacji .NET Framework używa [kodowania UTF-16][].Many .NET Framework applications use UTF-16. Z przyczyn historycznych jest to czasami nazywane "Unicode", terminem, który obecnie odwołuje się do szerokiej normy , która obejmuje zarówno UTF-8 i UTF-16.For historical reasons, this is sometimes called "Unicode", a term that now refers to a broad standard that includes both UTF-8 and UTF-16.
  • W systemie Windows wiele natywnych aplikacji, które są wstępnie używane w formacie Unicode, nadal domyślnie używają systemu Windows-1252.On Windows, many native applications that predate Unicode continue to use Windows-1252 by default.

Kodowanie Unicode ma również koncepcję znacznika kolejności bajtów (BOM).Unicode encodings also have the concept of a byte-order mark (BOM). Specyfikacje BOM są wyszukiwane na początku tekstu, aby poinformować dekoder, który jest używany do kodowania tekstu.BOMs occur at the beginning of text to tell a decoder which encoding the text is using. W przypadku kodowania wielobajtowego BOM zawiera również bajty kodowania.For multi-byte encodings, the BOM also indicates endianness of the encoding. Specyfikacje BOM są zaprojektowane jako bajty rzadko występujące w tekście innym niż Unicode, co pozwala na rozsądne odgadnięcie tekstu w formacie Unicode, gdy jest obecny BOM.BOMs are designed to be bytes that rarely occur in non-Unicode text, allowing a reasonable guess that text is Unicode when a BOM is present.

Specyfikacje BOM są opcjonalne i ich przyjęcie nie jest tak popularne w świecie systemu Linux, ponieważ jest ona używana wszędzie.BOMs are optional and their adoption isn't as popular in the Linux world because a dependable convention of UTF-8 is used everywhere. Większość aplikacji systemu Linux zakłada, że wprowadzanie tekstu jest zakodowane w UTF-8.Most Linux applications presume that text input is encoded in UTF-8. Chociaż wiele aplikacji systemu Linux rozpozna i prawidłowo obsłuży BOM, liczba nie, co prowadzi do artefaktów w tekście manipulowanym tymi aplikacjami.While many Linux applications will recognize and correctly handle a BOM, a number do not, leading to artifacts in text manipulated with those applications.

W związku z tym :Therefore :

  • Jeśli pracujesz głównie z aplikacjami systemu Windows i programem Windows PowerShell, należy preferować kodowanie takie jak UTF-8 z BOM lub UTF-16.If you work primarily with Windows applications and Windows PowerShell, you should prefer an encoding like UTF-8 with BOM or UTF-16.
  • Jeśli pracujesz na różnych platformach, należy preferować kodowanie UTF-8 z BOM.If you work across platforms, you should prefer UTF-8 with BOM.
  • Jeśli pracujesz głównie w kontekstach skojarzonych z systemem Linux, należy preferować kodowanie UTF-8 bez BOM.If you work mainly in Linux-associated contexts, you should prefer UTF-8 without BOM.
  • Systemy Windows-1252 i Latin-1 są zasadniczo starszymi kodowaniami, które należy unikać, jeśli jest to możliwe.Windows-1252 and latin-1 are essentially legacy encodings that you should avoid if possible. Jednak niektóre starsze aplikacje systemu Windows mogą być od nich zależne.However, some older Windows applications may depend on them.
  • Warto również zauważyć, że podpisywanie skryptu jest zależne od kodowania, co oznacza, że zmiana kodowania w podpisanym skrypcie będzie wymagała ponownego podpisania.It's also worth noting that script signing is encoding-dependent, meaning a change of encoding on a signed script will require resigning.

Konfigurowanie VS CodeConfiguring VS Code

Domyślne kodowanie VS Code to UTF-8 bez BOM.VS Code's default encoding is UTF-8 without BOM.

Aby ustawić kodowanie vs Code, przejdź do ustawień vs Code (Ctrl + ,) i ustaw "files.encoding" ustawienie:To set VS Code's encoding, go to the VS Code settings (Ctrl+,) and set the "files.encoding" setting:

"files.encoding": "utf8bom"

Dostępne są następujące wartości:Some possible values are:

Listę rozwijaną dla tego elementu należy uzyskać w widoku graficznym GUI lub w widoku JSON.You should get a dropdown for this in the GUI view, or completions for it in the JSON view.

Możesz również dodać następujące elementy do autowykrywania kodowania, jeśli jest to możliwe:You can also add the following to autodetect encoding when possible:

"files.autoGuessEncoding": true

Jeśli nie chcesz, aby te ustawienia miały wpływ na wszystkie typy plików, VS Code również zezwala na konfiguracje językowe.If you don't want these settings to affect all files types, VS Code also allows per-language configurations. Utwórz ustawienie specyficzne dla języka, umieszczając ustawienia w [<language-name>] polu.Create a language-specific setting by putting settings in a [<language-name>] field. Przykład:For example:

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

Warto również rozważyć zainstalowanie [Narzędzia Gremlins śledzącego][] dla Visual Studio Code.You may also want to consider installing the Gremlins tracker for Visual Studio Code. To rozszerzenie ujawnia pewne znaki Unicode, które są łatwe do uszkodzenia, ponieważ są niewidoczne lub wyglądają podobnie jak inne normalne znaki.This extension reveals certain Unicode characters that easily corrupted because they are invisible or look like other normal characters.

Konfigurowanie programu PowerShellConfiguring PowerShell

Domyślne kodowanie programu PowerShell różni się w zależności od wersji:PowerShell's default encoding varies depending on version:

  • W programie PowerShell 6 + domyślne kodowanie to UTF-8 bez BOM na wszystkich platformach.In PowerShell 6+, the default encoding is UTF-8 without BOM on all platforms.
  • W programie Windows PowerShell domyślne kodowanie to zwykle Windows-1252, rozszerzenie Latin-1, znane także jako ISO 8859-1.In Windows PowerShell, the default encoding is usually Windows-1252, an extension of latin-1, also known as ISO 8859-1.

W programie PowerShell 5 można znaleźć domyślne kodowanie w następujący sposób:In PowerShell 5+ you can find your default encoding with this:

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

Poniższy skrypt może służyć do określania, jakie kodowanie sesja programu PowerShell wnioskuje o skrypt bez BOM.The following script can be used to determine what encoding your PowerShell session infers for a script without a 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
}

Istnieje możliwość skonfigurowania programu PowerShell w taki sposób, aby korzystał z danego kodowania bardziej ogólnie przy użyciu ustawień profilu.It's possible to configure PowerShell to use a given encoding more generally using profile settings. Zobacz następujące artykuły:See the following articles:

Nie można wymusić, aby program PowerShell używał określonego kodowania danych wejściowych.It's not possible to force PowerShell to use a specific input encoding. Program PowerShell 5,1 i jego starsze działania działają w systemie Windows z ustawieniami regionalnymi pl-US. domyślnie jest to kodowanie Windows-1252, gdy nie ma BOM.PowerShell 5.1 and below, running on Windows with the locale set to en-US, defaults to Windows-1252 encoding when there's no BOM. Inne ustawienia regionalne mogą korzystać z innego kodowania.Other locale settings may use a different encoding. Aby zapewnić współdziałanie, najlepszym rozwiązaniem jest zapisanie skryptów w formacie Unicode przy użyciu BOM.To ensure interoperability, it's best to save scripts in a Unicode format with a BOM.

Ważne

Wszystkie inne narzędzia, które są dostępne dla skryptów programu PowerShell, mogą mieć wpływ na Opcje kodowania lub zakodować skrypty do innego kodowania.Any other tools you have that touch PowerShell scripts may be affected by your encoding choices or re-encode your scripts to another encoding.

Istniejące skryptyExisting scripts

W przypadku skryptów znajdujących się już w systemie plików może być konieczne ponowne zakodowanie w nowym wybranym kodowaniu.Scripts already on the file system may need to be re-encoded to your new chosen encoding. Na dolnym pasku VS Code zobaczysz etykietę UTF-8.In the bottom bar of VS Code, you'll see the label UTF-8. Kliknij go, aby otworzyć pasek akcji, a następnie wybierz pozycję Zapisz z kodowaniem .Click it to open the action bar and select Save with encoding . Teraz można wybrać nowe kodowanie dla tego pliku.You can now pick a new encoding for that file. Aby uzyskać pełne instrukcje, zobacz kodowanie vs Code .See VS Code's encoding for full instructions.

Jeśli konieczne jest ponowne zakodowanie wielu plików, można użyć następującego skryptu:If you need to re-encode multiple files, you can use the following script:

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

Środowisko PowerShell Integrated Scripting Environment (ISE)The PowerShell Integrated Scripting Environment (ISE)

Jeśli edytujesz także skrypty za pomocą programu PowerShell ISE, musisz zsynchronizować ustawienia kodowania w tym miejscu.If you also edit scripts using the PowerShell ISE, you need to synchronize your encoding settings there.

ISE powinien przestrzegać BOM, ale można również użyć odbicia, aby ustawić kodowanie.The ISE should honor a BOM, but it's also possible to use reflection to set the encoding. Należy zauważyć, że nie można tego utrwalić między uruchomieniami.Note that this wouldn't be persisted between startups.

Oprogramowanie do kontroli źródłaSource control software

Niektóre narzędzia kontroli źródła, takie jak Git, ignorują kodowania; git po prostu śledzi liczbę bajtów.Some source control tools, such as git, ignore encodings; git just tracks the bytes. Inne, takie jak Azure DevOps lub Mercurial, mogą nie być.Others, like Azure DevOps or Mercurial, may not. Nawet niektóre narzędzia oparte na usłudze git korzystają z dekodowania tekstu.Even some git-based tools rely on decoding text.

W takim przypadku upewnij się, że:When this is the case, make sure you:

  • Skonfiguruj kodowanie tekstu w kontroli źródła, aby pasowało do konfiguracji VS Code.Configure the text encoding in your source control to match your VS Code configuration.
  • Upewnij się, że wszystkie pliki są zaewidencjonowane do kontroli źródła w odpowiednim kodowaniu.Ensure all your files are checked into source control in the relevant encoding.
  • Uważaj na zmiany kodowania otrzymanego za pomocą kontroli źródła.Be wary of changes to the encoding received through source control. Kluczową literą tego jest różnica wskazująca, że zmiany nie są zmieniane (ponieważ bajty nie mają znaków).A key sign of this is a diff indicating changes but where nothing seems to have changed (because bytes have but characters have not).

Środowiska współpracownikówCollaborators' environments

Przed skonfigurowaniem kontroli źródła upewnij się, że współpracownicy na wszystkich udostępnianych plikach nie mają ustawień, które zastępują kodowanie przez ponowne Kodowanie plików programu PowerShell.On top of configuring source control, ensure that your collaborators on any files you share don't have settings that override your encoding by re-encoding PowerShell files.

Inne programyOther programs

Każdy inny program, który odczytuje lub zapisuje skrypt programu PowerShell, może go następnie zakodować.Any other program that reads or writes a PowerShell script may re-encode it.

Przykłady to:Some examples are:

  • Używanie schowka do kopiowania i wklejania skryptu.Using the clipboard to copy and paste a script. Jest to typowy scenariusz, taki jak:This is common in scenarios like:
    • Kopiowanie skryptu do maszyny wirtualnejCopying a script into a VM
    • Kopiowanie skryptu z wiadomości e-mail lub strony sieci WebCopying a script out of an email or webpage
    • Kopiowanie skryptu do lub z dokumentu programu Microsoft Word lub PowerPointCopying a script into or out of a Microsoft Word or PowerPoint document
  • Inne edytory tekstu, takie jak:Other text editors, such as:
    • NotatnikNotepad
    • vimvim
    • Dowolny inny edytor skryptów programu PowerShellAny other PowerShell script editor
  • Narzędzia do edycji tekstu, takie jak:Text editing utilities, like:
    • Get-Content/Set-Content/Out-File
    • Operatory przekierowania programu PowerShell, takie jak > i >>PowerShell redirection operators like > and >>
    • sed/awk
  • Programy transferu plików, takie jak:File transfer programs, like:
    • Przeglądarka sieci Web, podczas pobierania skryptówA web browser, when downloading scripts
    • Udział plikówA file share

Niektóre z tych narzędzi zajmują się bajtami, a nie tekstem, ale inne oferują konfiguracje kodowania.Some of these tools deal in bytes rather than text, but others offer encoding configurations. W takich przypadkach należy skonfigurować kodowanie, aby zapobiec problemom, tak samo jak w przypadku kodowania edytora.In those cases where you need to configure an encoding, you need to make it the same as your editor encoding to prevent problems.

Inne zasoby dotyczące kodowania w programie PowerShellOther resources on encoding in PowerShell

Istnieje kilka innych wpisów dotyczących kodowania i konfigurowania kodowania w programie PowerShell, które są rozumiane jako przeczytane:There are a few other nice posts on encoding and configuring encoding in PowerShell that are worth a read: