I need to create a JSON file when launching an Angular e2e test, basing on gopass key. Unfortunately I'm getting JSON encoded as UTF-8 with BOM.
I created task in tasks.json launched by one of launch configuration, tried to configure it without success. Problem is caused by PowerShell, which by default write files with BOM characters. I was trying to change task type to process (run with key and output file as args too), but then I got problem with not selecting proper gopass key or with running command. I cannot make slight changes in my test code, so I need to set it by tasks.json/launch.json.
My current task configuration:
{
"type": "shell",
"label": "Get data",
"command": "gopass \"somekey\" > \"myFile.json\""
},
I want to get JSON file without BOM character
Theo's answer shows you how to make Visual Studio Code's default shell on Windows, Windows PowerShell, create BOM-less UTF-8 files, which, unfortunately, is quite cumbersome, because it isn't supported with standard operators and cmdlets.
The shortest formulation in your case would be to replace:
"command": "gopass \"somekey\" > \"myFile.json\""
with:
"command": "[IO.File]::WriteAllLines(\"$pwd\myFile.json\", (gopass \"somekey\"))"
To retain the convenience of defining your tasks.json
tasks as unmodified PowerShell command strings that can use >
, while also producing BOM-less UTF-8 output, you can make your task use PowerShell Core 7 as the shell instead, because its file-output cmdlets and redirection operators consistently default to BOM-less UTF8:
Prerequisite:
Make sure that PowerShell (Core) 7 is installed.
The bottom section shows how to perform automated on-demand installation.
If you're OK with globally substituting PowerShell (Core) 7 for Windows PowerShell - which then requires no change to your task definition:
Note: This means that the integrated terminal as well as all "shell"
-type tasks in tasks.json
will use PowerShell 7.
Open setting.json
(from the command palette, select > Preferences: Open Settings (JSON)
) and add the following property:
"terminal.integrated.defaultProfile.windows": "PowerShell",
Note: If pwsh.exe
is not in your system's PATH
, specify the full path in the "executable"
property; you can obtain it by opening a PowerShell 7 window and executing (Get-Process -Id $PID).Path
.
Alternatively, if you want to substitute PowerShell (Core) 7 for Windows PowerShell task-individually:
Add an "option"
object to your task-definition JSON to make it use PowerShell Core's CLI instead of Windows PowerShell's:
{
"type": "shell",
"label": "Get data",
"command": "gopass \"somekey\" > \"myFile.json\""
"options": {
"shell": {
"executable": "pwsh.exe",
"args": [ "-noprofile", "-command" ]
}
}
}
Since it is easy to perform an automated user-level installation of PowerShell 7, you can fully automate the whole process as follows:
In your project's tasks.json
file, define a new EnsurePsCoreInstalled
task that checks for the presence of PowerShell 7 and installs it, if it isn't already present.
It will be installed to $env:LOCALAPPDATA\powershell
.
As is to be expected, when the on-demand installation occurs (once per machine), there will be a noticeable delay.
Important: After the one-time installation Visual Studio Code won't find pwsh.exe
right away, so you need to either:
code
).{
"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": []
}
To make your Get Data
task execute task EnsurePsCoreInstalled
first, add the following property to it:
"dependsOn": "EnsurePsCoreInstalled"
Note: Doing so will slow down your task, because task EnsurePsCoreInstalled
will then be invoked first every time. While it quickly returns if it finds that PowerShell Core is already installed, Windows PowerShell itself, which runs the task, has a noticeable startup cost.