Reputation: 191
I am trying to create a Visual Studio Developer Powershell profile for Visual Studio Code. Here is what I tried:
"Developer Powershell": {
"path": "pwsh",
"args": [
"-noe",
"-c",
"\"&{$vsPath = &(Join-Path ${env:ProgramFiles(x86)} '\\Microsoft Visual Studio\\Installer\\vswhere.exe') -property installationpath; Import-Module (Join-Path $vsPath 'Common7\\Tools\\Microsoft.VisualStudio.DevShell.dll'); Enter-VsDevShell -VsInstallPath $vsPath -SkipAutomaticLocation}\""
],
"icon": "terminal-powershell"
}
I copied and pasted the arguments from my Windows Terminal profile, which works:
{
"commandline": "pwsh.exe -noe -c \"&{$vsPath = &(Join-Path ${env:ProgramFiles(x86)} '\\Microsoft Visual Studio\\Installer\\vswhere.exe') -property installationpath; Import-Module (Join-Path $vsPath 'Common7\\Tools\\Microsoft.VisualStudio.DevShell.dll'); Enter-VsDevShell -VsInstallPath $vsPath -SkipAutomaticLocation}\"",
"icon": "C:\\powershell\\713\\assets\\Square44x44Logo.png",
"name": "Developer PowerShell",
"startingDirectory": "%USERPROFILE%",
}
However, terminal output looks like this:
&{ = &(Join-Path C:\Program Files (x86) '\Microsoft Visual Studio\Installer\vswhere.exe') -property installationpath; Import-Module (Join-Path 'Common7\Tools\Microsoft.VisualStudio.DevShell.dll'); Enter-VsDevShell -VsInstallPath -SkipAutomaticLocation}
StaggoSTD
Note: I am using Oh My Posh here. That's why the last line looks weird without a nerd font.
So how do I make the Developer Powershell work? I tried using powershell
instead of pwsh
and removing the escaped double quotes but that did nothing.
Upvotes: 2
Views: 4042
Reputation: 1
Update on what mklement0 previously said (March 2023)
This worked for me. Modify last argument according to where your Powershell Developer is. I used Windows Terminal Settings to look up the proper path and args for my system.
"Developer PowerShell": {
"path": "powershell",
"color": "terminal.ansiMagenta",
"args": [
"-NoExit",
"-Command",
"$vsPath = & \"${env:ProgramFiles(x86)}/Microsoft Visual Studio/Installer/vswhere.exe\" -property installationpath; Import-Module \"${env:ProgramFiles(x86)}/Microsoft Visual Studio/2022/BuildTools/Common7/Tools/Microsoft.VisualStudio.DevShell.dll\"; Enter-VsDevShell cc62515d -SkipAutomaticLocation -DevCmdArguments '-arch=x64 -host_arch=x64'"
]
},
Upvotes: 0
Reputation: 437238
tl;dr
The following - which can be used as a property inside the "terminal.integrated.profiles.windows"
property of your settings.json
file in order to define a terminal profile named Developer PowerShell
- fixes the problems with your original attempt.
"Developer Powershell": {
"path": "pwsh",
"args": [
"-noexit",
"-c",
"$vsPath = & \"${env:ProgramFiles(x86)}/Microsoft Visual Studio/Installer/vswhere.exe\" -property installationpath; Import-Module \"$vsPath/Common7/Tools/Microsoft.VisualStudio.DevShell.dll\"; Enter-VsDevShell -VsInstallPath $vsPath -SkipAutomaticLocation"
],
"icon": "terminal-powershell"
}
Note:
Do not use this shell profile as your default profile - unless you've also configured explicitly configured an automation shell to be used for tasks and debugging, via a "terminal.integrated.automationProfile.windows"
property - see Terminal Profiles.
-Command <command>
to the shell command line (/d /c <command>
if cmd.exe
is the shell), which breaks if the shell profile itself already defines commands (rather than mere options) to execute on startup.Given that the assumption that environment variable ProgramFiles(x86)
expands to C:\Program Files (x86)
is pretty safe (though it is possible for it to expand to a different path on unusually configured systems), your own solution, which avoids use of ${env:ProgramFiles(x86)}
, should typically work just fine.
The solution above still uses ${env:ProgramFiles(x86)}
, and makes it work by including it in an embedded expandable string (\"...\"
) that constructs the path strings directly, not via Join-Path
. This not only simplifies the command, it avoids one of the original problems: use of ${env:ProgramFiles(x86)}
outside of a (PowerShell) string literal; the next section explains why that is a problem.
Another simplification is the use of /
as the path separator - which PowerShell accepts interchangeably with \
- which doesn't require escaping inside a JSON string.
Background information:
Since you're passing the PowerShell CLI arguments as an array, via the "args"
property, you should not additionally enclose the string passed to the -c
parameter in an embedded, escaped "..."
string (\"...\"
), because with "args"
it is Visual Studio Code that performs any necessary escaping when stitching together the command line ultimately invoked behind the scenes.
If you do use enclosure in \"...\"
, PowerShell ultimately sees your commands as a single, expandable string literal, whose expanded value is implicitly echoed - that is the symptom you saw; in simple terms, PowerShell ended up executing something like "$vsPath = ..."
, which attempts to expand (interpolate) variable $vsPath
, and since no such variable exists, it evaluates to the empty string, causing the following verbatim string to be output: = ...
To put it differently: With "args"
, you needn't worry about quoting for the command line: You simply formulate what each argument should be verbatim, and let VS Code do the escaping - however, there is JSON-related escaping you do need to perform, and there's the pitfall of VS Code rather than PowerShell potentially up-front expanding variable references such as ${env:ProgramFiles(x86)}
:
"
as \"
, \
as \\
; note that the pain of the latter can be eased by using /
as the path separator instead, which PowerShell accepts interchangeably with \
.${someName}
and ${someNameSpace:someName}
candidates for up-front expansion - not also $someName
and $someNameSpace:someName
$vsPath
or $env:USERNAME
are not subject to potential up-front expansion, but it may happen in cases where enclosure in {...}
is syntactically required in PowerShell, due to a nonstandard name such as ${env:ProgramFiles(x86)}
.env:
namespace, specifically, up-front expansion always happens (as with command:
, config:
, and input:
, but these aren't typically defined in PowerShell): VS Code expands a reference such as ${env:ProgramFiles(x86)}
to the verbatim value of that environment variable. That is, ${env:ProgramFiles(x86)}
is replaced with verbatim C:\Program Files (x86)
in the command string before PowerShell sees the string, and the lack of quoting around the value then causes a syntax error.'${env:ProgramFiles(x86)}'
or \"${env:ProgramFiles(x86)}\"
. Note that this assumes that the value itself contains no '
or "
, respectively; in cases where this assumption cannot be made, use the following workaround:(Get-Content 'env:ProgramFiles(x86)')
As an aside: It is unnecessary to enclose statements passed to -c
(-Command
) in & { ... }
- just use ...
(the statements) directly.
& { ... }
is required, but this has since been corrected.Upvotes: 4
Reputation: 157
There are a couple of challenges to customizing PowerShell Integrated Terminal Profiles to work together with Microsoft.VisualStudio.DevShell.dll
:
PowerShell.exe
, but pwsh.exe
).-Command
when using the "terminal.integrated.automationProfile.windows"
in settings.json
. So, don't use it. Instead...Microsoft.VisualStudio.DevShell.dll
. Kind of a pain, but it will have to do until the "terminal.integrated.automationProfile.windows"
works as expected.Configuring the integrated terminal profile:
"terminal.integrated.defaultProfile.windows": "Developer PowerShell",
"terminal.integrated.shellIntegration.enabled": false,
"terminal.integrated.shellIntegration.decorationsEnabled": "both",
"terminal.integrated.profiles.windows": {
"PowerShell": {
"source": "PowerShell",
"icon": "terminal-powershell"
},
"Command Prompt": {
"path": [
"${env:windir}\\Sysnative\\cmd.exe",
"${env:windir}\\System32\\cmd.exe"
],
"args": [],
"icon": "terminal-cmd"
},
"Git Bash": {
"source": "Git Bash"
},
"Developer PowerShell": {
"path": "C:\\Program Files\\PowerShell\\7\\pwsh.exe",
"icon": "terminal-powershell",
"args": [
"-noexit",
"-Command",
"Import-Module 'C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/Common7/Tools/Microsoft.VisualStudio.DevShell.dll'; Enter-VsDevShell -VsInstallPath 'C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools' -SkipAutomaticLocation;"
]
}
Configuring Microsoft.VisualStudio.DevShell.dll
for Specific Tasks:
{
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "MyApp.API - Debug",
"detail": "Clean and Precompile API.",
"dependsOn": "MyApp.API - Clean",
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"clear": false,
"echo": true,
"panel": "shared"
},
"problemMatcher": [
"$msCompile"
],
"options": {
"shell": {
"executable": "C:\\Program Files\\PowerShell\\7\\pwsh.exe",
"args": [
"-NoProfile",
"-ExecutionPolicy",
"Bypass",
"-Command",
"Import-Module 'C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/Common7/Tools/Microsoft.VisualStudio.DevShell.dll'; Enter-VsDevShell -VsInstallPath 'C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools' -SkipAutomaticLocation;"
]
}
},
"command": "cl.exe",
"args": [
"/c",
"/std:c++20",
"/permissive-",
"/await",
"/bigobj",
"/utf-8",
"/MTd",
"/sdl",
"/Gr",
"/GL",
"/Zo",
"/Z7",
"/EHsc",
"/FC",
"/Fd:",
"Build/Debug/pch.pdb",
"/Fo:",
"Build/Debug/",
"Include/pch.cpp",
"/Ycpch.h",
"/FpBuild/Debug/pch.pch"
]
}
]
}
}
Upvotes: 1
Reputation: 191
I have figured it out. Firstly, I would like to give credit to mklement0, who has submitted an answer on simplifying the arguments, however it has been deleted. Using this, I replaced ${env:ProgramFiles(x86)}
with 'C:\\Program Files (x86)'
and everything went smoothly. To check if everything was properly working, I ran gcm fsi
, which told me that F# Interative was there, even though it is not on my normal PATH
. Here is my profile now for anybody who wants Developer Powershell in VSCode:
"Developer Powershell": {
"path": "pwsh",
"args": [
"-noe",
"-c",
"$vsPath = &(Join-Path 'C:\\Program Files (x86)' '\\Microsoft Visual Studio\\Installer\\vswhere.exe') -property installationpath; Import-Module (Join-Path $vsPath 'Common7\\Tools\\Microsoft.VisualStudio.DevShell.dll'); Enter-VsDevShell -VsInstallPath $vsPath -SkipAutomaticLocation"
],
"icon": "terminal-powershell"
}
As for why the environment variable was there, I copied and pasted from a Microsoft blog. Because it worked for Windows Terminal, I thought it worked for VSCode too. However, every other place I looked for a Developer Powershell profile, the environment variable wasn't used. Later on, I found out that I can just copy from the shortcut at C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio 2019\Visual Studio Tools
.
Upvotes: 2