When using Start-Process
with -Verb RunAs
, a -WorkingDirectory
argument is honored if the target executable is a .NET executable; examples:
pwsh.exe
(the PowerShell (Core) CLI) does honor it.
cmd.exe
and, curiously, powershell.exe
(the Windows PowerShell CLI) do not, and invariably use C:\Windows\System32
.
- The problem exists at the level of the .NET API that PowerShell uses behind the scenes (see
System.Diagnostics.ProcessStartInfo
), as of this writing (.NET 6.0.0-preview.4.21253.7).
Unless you know that you're invoking a .NET executable, a workaround that changes to the desired working folder in the new process is therefore required; to offer a more robust alternative to ふゆな's helpful answer:
$dir = $PWD.ProviderPath # use the current dir.
Start-Process -Verb RunAs powershell.exe @"
-noexit -c Set-Location -LiteralPath "$dir"
"@
The embedded "..."
quoting around $dir
ensures that paths with spaces are also handled correctly. (To use the current directory without an intermediate variable, replace "dir"
with "$($PWD.ProviderPath)"
.
- Using a here-string (
@"<newline>...<newline>"@
) isn't strictly necessary, but simplifies the embedded quoting; with a regular expandable string ("..."
), the embedded "
must be escaped as `"
(or ""
).
Using $PWD
's .ProviderPath
property ensures that a file-system-native path is used (based on drive letters also seen in cmd.exe
, for instance), given that the calling session's current location may be based on a PowerShell-only drive (see New-PSDrive
) that the elevated process may not have defined (at all or not based on the same root location).
- Caveat: If the native path is on a mapped network drive, this won't work, because elevated processes do not see the same drive mappings; in that event, pass the underlying UNC path.
Workaround for launching a GUI application elevated from a given working directory:
Since changing to the working directory must happen in the new, elevated process, a helper shell process is needed to perform this operation, which is best done via cmd.exe
(for better performance):
$exeToLaunch = 'Notepad.exe' # may include arguments
$dir = $PWD.ProviderPath # use the current dir.
Start-Process -Verb RunAs -WindowStyle Hidden cmd.exe @"
/c cd "$dir" & $exeToLaunch
"@