如何创建 VSCode 任务创建没有 BOM 的文件

How to create VSCode task creating a file without BOM

我需要在启动 Angular e2e 测试时基于 gopass 密钥创建一个 JSON 文件。不幸的是,我得到 JSON 编码为带有 BOM 的 UTF-8。

我在 tasks.json 中创建了通过启动配置之一启动的任务,尝试配置它但没有成功。问题是由 PowerShell 引起的,它默认写入带有 BOM 字符的文件。 我试图将任务类型更改为处理(运行 也将密钥和输出文件作为参数),但后来我遇到了没有选择正确的 gopass 密钥或使用 运行ning 命令的问题。 我不能对我的测试代码做细微的改动,所以我需要通过任务来设置它。json/launch.json.

我当前的任务配置:

{
    "type": "shell",
    "label": "Get data",
    "command": "gopass \"somekey\" > \"myFile.json\""
},

我想获取 JSON 没有 BOM 字符的文件

据我了解,从 PowerShell 版本 6 开始,Set-ContentOut-File 都支持 UTF8NoBOM 编码。

如果您的版本低于 6.0,您可以使用以下任一代码将 json 字符串保存为不带 BOM 的 UTF8:

$json = @"
{
    "type": "shell",
    "label": "Get data",
    "command": "gopass \"somekey\" > \"myFile.json\""
}
"@

使用 UTF8Encoding 对象并将 encoderShouldEmitUTF8Identifier 参数设置为 $false

$Utf8NoBom = New-Object System.Text.UTF8Encoding $false
[System.IO.File]::WriteAllText('D:\launch.json', $json, $Utf8NoBom)

使用一个 StreamWriter 对象,它默认输出没有 BOM 的 UTF8

$sw = New-Object System.IO.StreamWriter 'D:\launch.json'
$json | Out-String -Stream | ForEach-Object { $sw.Write($_) }
$sw.Dispose()

如果你使用set-content,就不会有bom。 PS 5 中的默认值是 "ansi".

或者您可能在谈论 vscode 本身?保存的默认编码是utf8 no bom.

向您展示如何在 Windows、Windows PowerShell 上创建 Visual Studio 代码的默认值 shell , 创建 BOM-less UTF-8 文件,不幸的是,这非常麻烦,因为标准运算符和 cmdlet 不支持它。

在你的情况下最短的公式是替换:

"command": "gopass \"somekey\" > \"myFile.json\""

与:

"command": "[IO.File]::WriteAllLines(\"$pwd\myFile.json\", (gopass \"somekey\"))"

保留将 tasks.json 任务定义为可以使用 > 的未修改 PowerShell 命令字符串 的便利性,同时还生成无 BOM 的 UTF- 8 输出,您可以 让您的任务使用 PowerShell Core (v6+) 作为 shell,因为 PowerShell Core 的文件输出 cmdlet 和运算符一致 default 到 BOM-less UTF8:

先决条件:确保安装了PowerShell Core
底部 显示如何执行自动按需安装

注意:最终,PowerShell Core 将与遗留 Windows PowerShell 一起预装在 Windows 上版本,但这 (a) 暂时不会发生,并且 (b) 没有具体的时间框架。


  • 如果您同意 globally 用 PowerShell Core 替换 Windows PowerShell - 这样就不需要更改您的任务定义:

注意:这意味着 集成终端 以及 tasks.json 中所有 "shell" 类型的任务将使用 PowerShell Core .

打开 setting.json(从命令面板,select > Preferences: Open Settings (JSON))并添加以下内容 属性:

    "terminal.integrated.shell.windows": "pwsh.exe"

注意:如果 pwsh.exe 不在您系统的 PATH 中,请在 "executable" 中指定 完整 路径属性;您可以通过打开 PowerShell Core window 并执行 (Get-Process -Id $PID).Path.

来获取它
  • 如果您想用 PowerShell Core 替换 WindowsPowerShell task-individually:

"option" 对象添加到您的任务定义 JSON 以使其使用 PowerShell Core 的 CLI 而不是 Windows PowerShell 的:

{
    "type": "shell",
    "label": "Get data",
    "command": "gopass \"somekey\" > \"myFile.json\""
    "options": {
      "shell": {
         "executable": "pwsh.exe",
         "args": [ "-noprofile", "-command" ]
      }
    }
}

在 Windows 上使用自动 按需 安装 PowerShell Core:

由于执行 PowerShell Core 的自动化用户级安装很容易,您可以按如下方式完全自动化整个过程:

  • 定义一个新的 EnsurePsCoreInstalled 任务来检查是否存在 PowerShell Core 并在需要时安装它。

    • 它将安装到 $env:LOCALAPPDATA\powershell
    • 当然,当按需安装发生时(每台机器一次),会有明显的延迟。
    • 重要提示:一次性安装后Visual Studio代码不会立即找到pwsh.exe ,所以你需要:
      • 从 Windows 注销并重新打开(或重新启动),然后重新启动 Visual Studio 代码
      • 退出 Visual Studio 代码,打开 new PowerShell window 并从那里重新启动它(只需 运行 code) .
      • 这个要求很不幸,但是 Visual Studio 从 v1.37 开始的代码不接受会话中的环境变化;如果您希望看到改变,请投票给 feature request on GitHub
{
    "label": "EnsurePsCoreInstalled",
    "type": "process",
    "command": "powershell.exe",
    "args": [
        "-noprofile",
        "-command",
        "if (gcm -ea ignore pwsh) { exit 0 }; Write-Verbose -vb 'Installing PowerShell Core...'; iex \"& { $(irm https://aka.ms/install-powershell.ps1) }\"; $dir = $env:LocalAppData + '\Microsoft\PowerShell'; $userPath = [Environment]::GetEnvironmentVariable('Path', 'User') -split ';' -ne ''; if ($dir -notin $userPath) { [Environment]::SetEnvironmentVariable('Path', ($userPath + $dir) -join ';', 'User') }; $env:Path += ';' + $dir; if (gcm -ea ignore pwsh) { Throw 'PowerShell Core was just installed on demand. To make it usable, log off and on again or reboot, or restart Visual Studio Code from a new PowerShell window (run `code`).' } else { Throw 'Installation of PowerShell Core FAILED.' }"
    ],
    "problemMatcher": []
}
  • 要使您的 Get Data 任务首先执行任务 EnsurePsCoreInstalled,请向其中添加以下 属性:
    • "dependsOn": "EnsurePsCoreInstalled"
    • 注意:这样做会减慢您的任务,因为任务 EnsurePsCoreInstalled 将首先被调用 每次 。虽然它很快 returns 如果它发现 PowerShell Core 已经安装,Windows PowerShell 本身,运行 的任务,有一个明显的启动成本。