I am trying to set up my right click context menu to launch both CMD and PowerShell5 at the current directory. My PowerShell 7 commands work fine.
This is what I got:
The registry command to open PowerShell5 as Admin is as follows:
PowerShell -Command "Start-Process cmd -ArgumentList '/s,/k,pushd %V && start PowerShell -NoExit && exit' -Verb RunAs"
The registry command to open the Command Prompt as Admin is as follows:
pwsh -noprofile -windowstyle hidden -Command "Start-Process cmd.exe -ArgumentList '/s,/k,pushd,%V' -Verb RunAs"
The registry command I have to open the Node command prompt is this:
cmd.exe /s /k "pushd "%V" & "C:\Program Files\nodejs\nodevars.bat""
(I couldn't figure out how to open the node prompt as admin).
Today, I realized that all of these commands fail if the directory I'm opening to has an apostrophe in the path or folder name. I've tried so many different registry commands and combinations of quotes and escape characters and nothing is working. It's getting enormously frustrating.
Does anyone know of any working commands to open both CMD and PowerShell 5 in directories that have an apostrophe?
Any help at all would be greatly appreciated.
The keys to the solution are:
Launch via cmd.exe
and pipe (|
) the literal folder path being passed via %V
to powershell.exe
:
cmd /c <NUL set /p="%V"
is a trick that echoes the value of %V
without double quotes, even if the value contains cmd.exe
metacharacters (it also echoes without a trailing newline, but that is not a problem here).
In the powershell.exe
command line being piped to, the folder path can then be referenced indirectly, via the automatic $input
variable, which provides access to the stdin (piped) input.
%V
were embedded directly in the command line, notably with respect to paths containing $
and `
characters.Also, the PowerShell command can perform string replacement on the value of $env:_dir
in order to double embedded '
chars, which allows embedding the value in a verbatim '...'
string.
Nested "..."
quoting for PowerShell requires intricate escaping using \
as the escape character.
Note: The commands invariably cause creation of a auxiliary, transitory console window, which the PowerShell commands hide as quickly possible and which then auto-closes. This will cause some brief visual disruption.
Note:
The following commands are designed to be placed verbatim in the registry. Doing so programmatically complicates escaping further.
The commands use powershell.exe
, the Windows PowerShell CLI, but they should also work with pwsh.exe
, the cross-platform, install-on-demand PowerShell (Core) 7+ CLI; depending on how you installed the latter, you may have to use its full path in the commands below.
You can test-drive the commands as follows:
%V
with the literal path of a folder of interest.Run
dialog (WinKey-R).Commands for elevated sessions (run as admin):
A powershell.exe
(Windows PowerShell) sesssion:
cmd /c <NUL set /p="%V" | powershell.exe -WindowStyle Hidden -NoProfile -Command "Start-Process -Verb RunAs powershell.exe -ArgumentList ('-NoExit -Command \"Push-Location -LiteralPath ''{0}''\"' -f $input.Replace(\"'\", \"''\"))"
A cmd.exe
session:
cmd /c <NUL set /p="%V" | powershell.exe -WindowStyle Hidden -NoProfile -Command "Start-Process -Verb RunAs cmd -ArgumentList \"/k pushd \"\"$input\"\"\""
A cmd.exe
session with the Node.js environment set up:
cmd /c <NUL set /p="%V" | powershell.exe -WindowStyle Hidden -NoProfile -Command "Start-Process -Verb RunAs cmd -ArgumentList \"/k pushd \"\"$input\"\" ^& \"\"C:\Program Files\nodejs\nodevars.bat\"\"\""
Note: If you wanted to use environment-variable %ProgramFiles%
instead of hard-coding C:\Program Files
as part of the Node.js initialization-batch file path for increased robustness, you'd have to define the registry value as REG_EXPAND_SZ
.
Running wt.exe
(Windows Terminal), as discovered by you, with the notable need to escape ;
chars. in the path as \;
, because ;
is a metacharacter on the wt.exe
command line).
cmd /c <NUL set /p="%V" | powershell.exe -WindowStyle Hidden -NoProfile -Command "Start-Process -Verb RunAs wt.exe -ArgumentList (\"-d \"\"{0}\" -f $input.Replace(';','\;'))"
Note: This approach is shell-agnostic. That is, Windows Terminal itself sets the working directory and then runs whatever shell is configured to be its default.
Commands for non-elevated sessions:
The need for nested invocation of PowerShell then falls away, which simplifies the commands.
However, for opening a PowerShell session special considerations apply:
A different approach for passing the folder path verbatim is required: an auxiliary environment variable, _dir
is set, which the PowerShell commands can access as $env:_dir
.
The visual disruption by an auxiliary, transitory console window, you have two options with the following tradeoffs:
Avoid the disruption, which has the disadvantage that cmd.exe
's console-window settings are applied (and that the initial cmd.exe
process used to launch the PowerShell session stays alive as the PowerShell process' parent process; they terminate together, however).
Live with the disruption (as is inevitable with elevation), which has the advantage that the usual console settings associated with the PowerShell executable are used.
No visual disruption, but use of cmd.exe
's console-window settings even for PowerShell:
A powershell.exe
session:
cmd /c title Windows^ PowerShell & pushd "%V" & powershell.exe
A cmd.exe
session (append & "C:\Program Files\nodejs\nodevars.bat"
for the Node.js initialization):
cmd /k pushd "%V"
Visual disruption, but use of PowerShell's console-window settings:
A powershell.exe
session:
cmd /c pushd "%V" & start powershell.exe
Note:
The above will use PowerShell's usual console-window settings, but show the full executable path as the window's title.
While you could change the title with start "Windows PowerShell" powershell.exe
, for instance, default settings then apply - you could customize them, however.
An alternative is to change the window title from inside PowerShell (however, the change won't take effect until PowerShell is fully loaded):
cmd /c pushd "%V" & start powershell.exe -NoExit -Command [Console]::Title='Windows PowerShell'
Finally, if you invoke pwsh.exe
by its full path and that path contains spaces, you need to double-quote the spaces individually, because double-quoting the path as a whole would cause it to be being mistaken for the window title argument (if you explicitly pass an (of necessity double-quoted) title argument, no extra work is needed); e.g.:
:: Note the individually quoted space (" ")
cmd /c pushd "%V" & start C:\PowerShell" "7\pwsh.exe