VS Code と PowerShell でのファイル エンコードについて
VS Code を使用して PowerShell スクリプトを作成および編集する場合は、正しい文字エンコード形式を使用してファイルを保存することが重要です。
ファイル エンコードとは何ですか。また、なぜそれが重要なのでしょうか。
VS Code は、バッファーに文字の文字列を入力する人間と、ファイル システムへのバイト ブロックの読み取り/書き込みの間のインターフェイスを管理します。 VS Code は、ファイルを保存するときに、テキスト エンコードを使用して、各文字のバイト数を決定します。 詳細については、about_Character_Encodingを参照してください。
同様に、PowerShell でスクリプトを実行する場合は、ファイル内のバイトを文字に変換して、ファイルを PowerShell プログラムに再構築する必要があります。 VS Code はファイルを書き込み、PowerShell はファイルを読み取るので、同じエンコード システムを使用する必要があります。 PowerShell スクリプトを解析するこのプロセスでは、バイト ->文字 ->トークン - 抽象構文ツリー> ->実行。
VS Code と PowerShell はどちらも、適切な既定のエンコード構成でインストールされます。 ただし、PowerShell 6 のリリースでは、PowerShell で使用される既定のエンコードが変更されました。 VS Code で PowerShell または PowerShell 拡張機能を使用しても問題がないことを確認するには、VS Code と PowerShell の設定を正しく構成する必要があります。
エンコードの問題の一般的な原因
エンコードの問題は、VS Code またはスクリプト ファイルのエンコードが PowerShell の想定されるエンコードと一致しない場合に発生します。 PowerShell でファイル エンコードを自動的に決定する方法はありません。
7 ビット ASCII 文字セットに含まれていない文字を使用している場合は、エンコードの問題が発生可能性が高くなります。 例えば:
- em-dash (
—
)、改行しないスペース ("
) などの拡張文字以外の文字 - アクセント付きラテン文字 (
É
,ü
) - キリル文字 (
Д
、Ц
) のようなラテン文字以外の文字 - CJK 文字 (
本
,화
,が
)
エンコードの問題の一般的な理由は次のとおりです。
- VS Code と PowerShell のエンコードは、既定値から変更されていません。 PowerShell 5.1 以下では、既定のエンコードは VS Code とは異なります。
- 別のエディターが開き、新しいエンコードでファイルが上書きされました。 これは多くの場合、ISE で発生します。
- ファイルは、VS Code または PowerShell で想定されているものとは異なるエンコードでソース管理にチェックインされます。 これは、コラボレーターが異なるエンコード構成のエディターを使用する場合に発生する可能性があります。
エンコードの問題が発生したタイミングを確認する方法
多くの場合、エンコード エラーはスクリプトの解析エラーとして表示されます。 スクリプトで奇妙な文字シーケンスが見つかると、これが問題になる可能性があります。 次の例では、â€"
文字としてダッシュ (–
) が表示されます。
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 としてデコードされると、â€"
文字として解釈されます。
次のような奇妙な文字シーケンスが表示されることがあります。
-
–
の代わりにâ€"
する (ダッシュ付き) -
—
の代わりにâ€"
(em-dash) -
Ä
ではなくÄ2
-
Â
する (改行しないスペース) -
é
ではなくé
この便利な リファレンス は、UTF-8/Windows-1252 エンコードの問題を示す一般的なパターンを示しています。
VS Code の PowerShell 拡張機能がエンコードと対話する方法
PowerShell 拡張機能は、さまざまな方法でスクリプトと対話します。
- VS Code でスクリプトを編集すると、VS Code によって拡張機能にコンテンツが送信されます。 言語サーバー プロトコル では、このコンテンツを UTF-8 で転送することが義務付けられています。 そのため、拡張機能が間違ったエンコードを取得することはできません。
- 統合コンソールでスクリプトを直接実行すると、PowerShell によってファイルから直接読み取られます。 PowerShell のエンコードが VS Code と異なる場合は、ここで問題が発生する可能性があります。
- VS Code で開いているスクリプトが VS Code で開いていない別のスクリプトを参照すると、拡張機能はファイル システムからそのスクリプトのコンテンツを読み込むのにフォールバックします。 PowerShell 拡張機能は既定で UTF-8 エンコードですが、バイトオーダー マーク(BOM) 検出
使用して正しいエンコードを選択します。
この問題は、BOM なしの形式 (BOM なしの UTF-8
適切なエンコードの選択
さまざまなシステムとアプリケーションで、異なるエンコードを使用できます。
- .NET Standard、web、Linux の世界では、UTF-8 が主要なエンコードになりました。
- 多くの .NET Framework アプリケーションでは、UTF-16
使用されます。 歴史的な理由から、これは "Unicode" と呼ばれることもあります。これは、UTF-8 と UTF-16 の両方を含む広範な 標準 を指す用語です。 - Windows では、Unicode より前の多くのネイティブ アプリケーションでは、既定で Windows-1252 が引き続き使用されます。
Unicode エンコードには、バイトオーダー マーク (BOM) の概念もあります。 BOM はテキストの先頭で発生し、テキストがどのエンコードを使用するかをデコーダーに伝えます。 マルチバイト エンコードの場合、BOM はエンコードのエンディアン
BOM は省略可能であり、UTF-8 の信頼できる規則がどこでも使用されるため、Linux の世界では採用がそれほど普及していません。 ほとんどの Linux アプリケーションでは、テキスト入力が UTF-8 でエンコードされていることが前提です。 多くの Linux アプリケーションは BOM を認識して正しく処理しますが、数値は認識せず、テキスト内のアーティファクトがそれらのアプリケーションで操作されます。
したがって、次の。
- 主に Windows アプリケーションと Windows PowerShell を使用する場合は、BOM または UTF-16 を使用した UTF-8 などのエンコードを使用することをお勧めします。
- 複数のプラットフォームで作業する場合は、BOM で UTF-8 を使用することをお勧めします。
- 主に Linux 関連のコンテキストで作業する場合は、BOM なしの UTF-8 を使用する必要があります。
- Windows-1252 と latin-1 は基本的にレガシ エンコードであり、可能であれば避ける必要があります。 ただし、一部の古い Windows アプリケーションはそれらに依存している場合があります。
- また、スクリプト署名はエンコードに依存する
されていることにも注目してください。つまり、署名されたスクリプトのエンコードを変更するには、再署名が必要になります。
VS Code の構成
VS Code の既定のエンコードは、BOM なしの UTF-8 です。
VS Code のエンコード
"files.encoding": "utf8bom"
使用可能な値は次のとおりです。
-
utf8
: [UTF-8] (BOM なし) -
utf8bom
: [UTF-8] と BOM -
utf16le
: リトル エンディアン [UTF-16] -
utf16be
: ビッグ エンディアン [UTF-16] -
windows1252
: [Windows-1252]
このドロップダウンは GUI ビューに表示されるか、JSON ビューで完了します。
可能な場合は、自動検出エンコードに次のコードを追加することもできます。
"files.autoGuessEncoding": true
これらの設定がすべてのファイルの種類に影響しないようにする場合、VS Code では言語ごとの構成も許可されます。
[<language-name>]
フィールドに設定を配置して、言語固有の設定を作成します。 例えば:
"[powershell]": {
"files.encoding": "utf8bom",
"files.autoGuessEncoding": true
}
Visual Studio Code 用の Gremlins トラッカー のインストールを検討することもできます。 この拡張機能では、見えないか、他の通常の文字のように見えるため、破損しやすい特定の Unicode 文字が表示されます。
PowerShell の構成
PowerShell の既定のエンコードは、バージョンによって異なります。
- PowerShell 6 以降では、既定のエンコードは、すべてのプラットフォームで BOM なしの UTF-8 です。
- 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, @())
}
次の スクリプト を使用して、BOM なしでスクリプトに対して PowerShell セッションが推論するエンコードを決定できます。
$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 を構成できます。 次の記事を参照してください。
Stack Overflowでの PowerShell エンコードに関する の回答です。 - powerShellでの BOM レス UTF-8 入力の処理に関するブログ記事
。
PowerShell で特定の入力エンコードを強制的に使用することはできません。 ロケールが en-USに設定された Windows で実行されている PowerShell 5.1 以下では、BOM がない場合は、既定で Windows-1252 エンコードが使用されます。 その他のロケール設定では、別のエンコードが使用される場合があります。 相互運用性を確保するには、BOM を使用して Unicode 形式でスクリプトを保存することをお勧めします。
大事な
PowerShell スクリプトにタッチするその他のツールは、エンコードの選択によって影響を受けたり、スクリプトを別のエンコードに再エンコードしたりする可能性があります。
既存のスクリプト
既にファイル システム上にあるスクリプトは、新しく選択したエンコードに再エンコードする必要がある場合があります。 VS Code の下部のバーに、UTF-8 というラベルが表示されます。 それをクリックしてアクション バーを開き、[エンコードで保存
複数のファイルを再エンコードする必要がある場合は、次のスクリプトを使用できます。
Get-ChildItem *.ps1 -Recurse | ForEach-Object {
$content = Get-Content -Path $_
Set-Content -Path $_.Fullname -Value $content -Encoding UTF8 -PassThru -Force
}
PowerShell 統合スクリプト環境 (ISE)
PowerShell ISE を使用してスクリプトも編集する場合は、そこでエンコード設定を同期する必要があります。
ISE は BOM を尊重する必要がありますが、リフレクションを使用してエンコード
ソース管理ソフトウェア
git などの一部のソース管理ツールでは、エンコードは無視されます。git はバイトを追跡するだけです。 Azure DevOps や Mercurial などの他のユーザーは、そうでない場合があります。 一部の Git ベースのツールでも、テキストのデコードに依存しています。
この場合は、次の操作を行ってください。
- VS Code の構成に合わせてソース管理のテキスト エンコードを構成します。
- すべてのファイルが関連するエンコードでソース管理にチェックインされていることを確認します。
- ソース管理を通じて受け取ったエンコードの変更に注意してください。 この重要な兆候は、変更を示す差分ですが、何も変更されていないようです (バイトには文字がないからです)。
コラボレーターの環境
ソース管理を構成する上で、共有するすべてのファイルのコラボレーターに、PowerShell ファイルを再エンコードしてエンコードをオーバーライドする設定がないことを確認します。
その他のプログラム
PowerShell スクリプトの読み取りまたは書き込みを行うその他のプログラムは、再エンコードできます。
いくつかの例を次に示します。
- クリップボードを使用してスクリプトをコピーして貼り付けます。 これは、次のようなシナリオで一般的です。
- VM へのスクリプトのコピー
- 電子メールまたは Web ページからスクリプトをコピーする
- Microsoft Word または PowerPoint 文書に対するスクリプトのコピーまたはコピー
- 次のようなその他のテキスト エディター:
- メモ帳
- vim
- その他の PowerShell スクリプト エディター
- 次のようなテキスト編集ユーティリティ:
Get-Content
/Set-Content
/Out-File
-
>
や>>
などの PowerShell リダイレクト演算子 sed
/awk
- 次のようなファイル転送プログラム:
- スクリプトをダウンロードするときの Web ブラウザー
- ファイル共有
これらのツールの中には、テキストではなくバイト単位で処理するものもあれば、エンコード構成を提供するツールもあります。 エンコードを構成する必要がある場合は、問題を防ぐためにエディター エンコードと同じにする必要があります。
PowerShell でのエンコードに関するその他のリソース
PowerShell でのエンコードとエンコードの構成については、他にもいくつかの記事を読む価値があります。
- about_Character_Encoding
- Stack Overflow での PowerShell エンコードの
の概要を します - エンコードの問題について VS Code-PowerShell で開かれた以前の問題:
- ソフトウェアのクラシック Joel Unicode について書き上げる
- .NET Standard での
エンコード
PowerShell