Общие сведения о кодировке файлов в VS Code и PowerShell
При использовании VS Code для создания и редактирования скриптов PowerShell важно сохранить файлы с помощью правильного формата кодировки символов.
Что такое кодировка файлов и почему это важно?
VS Code управляет интерфейсом между человеческими строками символов в буфер и блоки чтения и записи байтов в файловую систему. При сохранении файла VS Code используется кодировка текста, чтобы решить, какие байты становятся каждым символом. Дополнительные сведения см. в about_Character_Encoding.
Аналогичным образом, когда PowerShell запускает скрипт, он должен преобразовать байты в файл в символы, чтобы восстановить файл в программу PowerShell. Так как VS Code записывает файл и PowerShell считывает файл, они должны использовать ту же систему кодирования. Этот процесс анализа скрипта PowerShell идет: байтов ->символов ->маркеров ->абстрактного дерева синтаксиса ->выполнения.
Vs Code и PowerShell устанавливаются с разумной конфигурацией кодирования по умолчанию. Однако кодировка по умолчанию, используемая PowerShell, изменилась с выпуском PowerShell 6. Чтобы не было проблем с использованием PowerShell или расширения PowerShell в VS Code, необходимо правильно настроить параметры VS Code и PowerShell.
Распространенные причины проблем с кодировкой
Проблемы с кодировкой возникают, когда кодировка VS Code или файл скрипта не соответствует ожидаемой кодировке PowerShell. Для PowerShell невозможно автоматически определить кодировку файлов.
При использовании символов, не входящих в 7-разрядныйнабор символов ASCII, скорее всего, возникают проблемы с кодировкой. Например:
- Расширенные символы, отличные от букв, такие как em-dash (
—
), неразрывное пространство ("
) - Акцентированные латинские символы (
É
,ü
) - Не латинские символы, такие как кириллица (
Д
,Ц
) - Символы CJK (
本
,화
,が
)
Распространенные причины проблем с кодировкой:
- Кодировки VS Code и PowerShell не были изменены по умолчанию. Для PowerShell 5.1 и ниже кодировка по умолчанию отличается от VS Code.
- Другой редактор открыл и перезаписал файл в новой кодировке. Это часто происходит с ISE.
- Файл проверяется в системе управления версиями в кодировке, отличной от ожидаемого VS Code или PowerShell. Это может произойти, когда сотрудники используют редакторы с различными конфигурациями кодирования.
Сведения о проблемах с кодировкой
Часто ошибки кодирования представляют собой ошибки синтаксического анализа в скриптах. Если в скрипте находятся странные последовательности символов, это может быть проблема. В приведенном ниже примере en-dash (–
) отображается как символы â€"
:
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 â€"From $from â€"To $recipient1 â€"Subject $subject ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Send-MailMessage], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.SendMailMessage
Эта проблема возникает, так как VS Code кодирует символ –
в UTF-8 в качестве 0xE2 0x80 0x93
байтов. Когда эти байты декодируются как Windows-1252, они интерпретируются как символы â€"
.
Некоторые странные последовательности символов, которые могут отображаться:
-
â€"
вместо–
(en-dash) -
â€"
вместо—
(em-dash) -
Ä2
вместоÄ
-
Â
вместо -
é
вместоé
Этот удобный справочник содержит общие шаблоны, указывающие на проблему кодирования UTF-8/Windows-1252.
Взаимодействие расширения PowerShell в VS Code с кодировками
Расширение PowerShell взаимодействует со скриптами несколькими способами:
- Когда скрипты редактируются в VS Code, содержимое отправляется VS Code в расширение. Протокол сервера языка требует передачи этого содержимого в UTF-8. Поэтому расширение не может получить неправильное кодирование.
- Когда скрипты выполняются непосредственно в интегрированной консоли, они считываются из файла с помощью PowerShell напрямую. Если кодировка PowerShell отличается от VS Code, то что-то может пойти не так здесь.
- Когда скрипт, открытый в VS Code, ссылается на другой скрипт, который не открыт в VS Code, расширение возвращается к загрузке содержимого этого скрипта из файловой системы. Расширение PowerShell по умолчанию использует кодировку UTF-8, но использует метку порядка байтовили BOM, чтобы выбрать правильную кодировку.
Проблема возникает при условии кодирования форматов без BOM (например, UTF-8 без BOM и Windows-1252). Расширение PowerShell по умолчанию используется для UTF-8. Расширение не может изменить параметры кодирования VS Code. Дополнительные сведения см. в статье проблема no 824.
Выбор правильной кодировки
Различные системы и приложения могут использовать разные кодировки:
- В .NET Standard, в Интернете и в мире Linux UTF-8 теперь является доминирующей кодировкой.
- Многие приложения .NET Framework используют UTF-16. По историческим причинам это иногда называется "Юникод", термин, который теперь относится к широкому стандартному, который включает как UTF-8, так и UTF-16.
- В Windows многие собственные приложения, которые предопределили Юникод, продолжают использовать Windows-1252 по умолчанию.
Кодировки Юникода также имеют концепцию метки порядка байтов (BOM). Boms возникает в начале текста, чтобы сообщить декодировщику, который кодирует текст. Для многобайтовых кодировок BOM также указывает конечную кодировки. BOM предназначены для байтов, которые редко происходят в тексте, отличном от Юникода, что позволяет разумно угадать, что текст юникода при наличии BOM.
BOM являются необязательными, и их внедрение не так популярны в мире Linux, так как зависимое соглашение UTF-8 используется везде. Большинство приложений Linux предполагают, что ввод текста закодирован в UTF-8. Хотя многие приложения Linux распознают и правильно обрабатывают BOM, число не выполняется, что приводит к артефактам в тексте, обрабатываемом этими приложениями.
поэтому:
- Если вы работаете в основном с приложениями Windows и Windows PowerShell, следует предпочесть кодировку, например UTF-8 с BOM или UTF-16.
- Если вы работаете на разных платформах, следует использовать UTF-8 с BOM.
- Если вы работаете главным образом в контекстах, связанных с Linux, следует предпочесть UTF-8 без BOM.
- Windows-1252 и latin-1 по сути являются устаревшими кодировками, которые следует избегать, если это возможно. Однако некоторые старые приложения Windows могут зависеть от них.
- Также стоит отметить, что подписывание скрипта зависимо от кодирования, то есть изменение кодировки в подписанном скрипте потребует отставки.
Настройка VS Code
Кодировка VS Code по умолчанию — UTF-8 без BOM.
Чтобы задать
"files.encoding": "utf8bom"
Ниже приведены некоторые возможные значения:
-
utf8
: [UTF-8] без BOM -
utf8bom
: [UTF-8] с BOM -
utf16le
: Маленький эндиан [UTF-16] -
utf16be
: Большой эндиан [UTF-16] -
windows1252
: [Windows-1252]
Вы должны получить раскрывающийся список для этого в представлении графического интерфейса пользователя или завершения для него в представлении JSON.
Вы также можете добавить следующее в кодировку autodetect, если это возможно:
"files.autoGuessEncoding": true
Если эти параметры не влияют на все типы файлов, VS Code также разрешает конфигурации на языке. Создайте параметр для конкретного языка, поместив параметры в поле [<language-name>]
. Например:
"[powershell]": {
"files.encoding": "utf8bom",
"files.autoGuessEncoding": true
}
Вам также может потребоваться установить трекер Gremlins для Visual Studio Code. Это расширение показывает определенные символы Юникода, которые легко повреждены, так как они невидимы или выглядят как другие обычные символы.
Настройка PowerShell
Кодировка PowerShell по умолчанию зависит от версии:
- В PowerShell 6+ кодировка по умолчанию — UTF-8 без BOM на всех платформах.
- В Windows PowerShell кодировка по умолчанию обычно является Windows-1252, которая является расширением latin-1 (также известной как ISO 8859-1).
В PowerShell 5+ вы можете найти кодировку по умолчанию с помощью следующего:
[psobject].Assembly.GetTypes() | Where-Object { $_.Name -eq 'ClrFacade'} |
ForEach-Object {
$_.GetMethod('GetDefaultEncoding', [System.Reflection.BindingFlags]'nonpublic,static').Invoke($null, @())
}
Следующий скрипт можно использовать для определения кодирования сеанса PowerShell для скрипта без 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
}
Можно настроить PowerShell для использования заданной кодировки в целом с помощью параметров профиля. См. следующие статьи:
- @mklement0ответ о кодировке PowerShell в Stack Overflow.
- @rkeithhillзапись блога о работе с входными данными UTF-8 без BOM в PowerShell.
Невозможно принудительно использовать кодирование входных данных PowerShell. PowerShell 5.1 и ниже, работающий в Windows с языковым стандартом, равным en-US, по умолчанию используется кодировка Windows-1252 при отсутствии BOM. Другие параметры языкового стандарта могут использовать другую кодировку. Чтобы обеспечить взаимодействие, рекомендуется сохранять скрипты в формате Юникода с помощью BOM.
Важный
Любые другие инструменты, которые касаются скриптов PowerShell, могут повлиять на выбор кодирования или повторно закодировать скрипты в другую кодировку.
Существующие скрипты
Скрипты, уже размещенные в файловой системе, могут быть перекодированы в новую выбранную кодировку. В нижней строке VS Code вы увидите метку UTF-8. Щелкните его, чтобы открыть панель действий и выберите Сохранить с помощью кодировки. Теперь вы можете выбрать новую кодировку для этого файла. Полные инструкции см. в кодировке VS Code.
Если необходимо повторно закодировать несколько файлов, можно использовать следующий сценарий:
Get-ChildItem *.ps1 -Recurse | ForEach-Object {
$content = Get-Content -Path $_
Set-Content -Path $_.Fullname -Value $content -Encoding UTF8 -PassThru -Force
}
Интегрированная среда сценариев PowerShell (ISE)
Если вы также редактируете скрипты с помощью среды сценариев PowerShell, необходимо синхронизировать параметры кодирования там.
IsE должен учитывать BOM, но также можно использовать отражение для задания кодировки. Обратите внимание, что это не будет сохранено между запусками.
Программное обеспечение управления версиями
Некоторые средства управления версиями, такие как git, игнорируют кодировки; Git просто отслеживает байты. Другие, такие как Azure DevOps или Mercurial, могут не быть. Даже некоторые средства на основе Git полагаются на декодирование текста.
В этом случае убедитесь, что вы:
- Настройте кодировку текста в системе управления версиями для сопоставления конфигурации VS Code.
- Убедитесь, что все файлы будут проверены в системе управления версиями в соответствующей кодировке.
- Будьте осторожны с изменениями в кодировке, полученной с помощью системы управления версиями. Ключевым признаком этого является дифф, указывающий на изменения, но где ничего не изменилось (так как байты имеют, но символы не имеют).
Среды участников совместной работы
На вершине настройки системы управления версиями убедитесь, что у ваших сотрудников в общих файлах нет параметров, переопределяющих кодировку, путем повторного кодирования файлов PowerShell.
Другие программы
Любая другая программа, которая считывает или записывает скрипт PowerShell, может повторно закодировать его.
Ниже приведены некоторые примеры.
- Использование буфера обмена для копирования и вставки скрипта. Это часто происходит в таких сценариях:
- Копирование скрипта в виртуальную машину
- Копирование скрипта из электронной почты или веб-страницы
- Копирование скрипта в документ Microsoft Word или PowerPoint или из него
- Другие текстовые редакторы, такие как:
- Блокнот
- энергия
- Любой другой редактор скриптов PowerShell
- Служебные программы редактирования текста, такие как:
Get-Content
/Set-Content
/Out-File
- Операторы перенаправления PowerShell, такие как
>
и>>
sed
/awk
- Программы передачи файлов, такие как:
- Веб-браузер при скачивании скриптов
- Общая папка
Некоторые из этих средств занимаются байтами, а не текстом, но другие предлагают конфигурации кодирования. В тех случаях, когда необходимо настроить кодировку, необходимо сделать его таким же, как кодирование редактора, чтобы предотвратить проблемы.
Другие ресурсы по кодировке в PowerShell
Есть несколько других хороших записей по кодировке и настройке кодирования в PowerShell, которые стоит прочитать:
- about_Character_Encoding
- @mklement0сводка по кодировке PowerShell в Stack Overflow
- Предыдущие проблемы, открытые в VS Code-PowerShell для проблем с кодировкой:
- Классический Джоэл на Software написать о Юникоде
- кодировка в .NET Standard
PowerShell