Thank you for your help.
I use Powershell in the Windows 10 command prompt and try to execute commands with administrative rights.
When I try the following three, a, b and c, I cannot start with "RunAs" as I think.
Does anyone know how to solve this problem?
(a) It can be executed successfully. The arguments are also passed correctly.
powershell.exe start-process -FilePath 'TestEnv.cmd' -ArgumentList '\"a\" \"B C\" \"d\"' -Verb Open
(b) Does not start after UAC confirmation.
powershell.exe start-process -FilePath 'TestEnv.cmd' -ArgumentList '\"a\" \"B C\" \"d\"' -Verb RunAs
(c) It is possible to invoke it, but the "B C" argument is not reflected in the "double quotes" argument, and "B C" is recognized separately.
powershell.exe start-process -FilePath 'TestEnv.cmd' -ArgumentList '"a" "B C" "d"' -Verb RunAs
Translated with www.DeepL.com/Translator (free version)
tl;dr
REM From cmd.exe (Command Prompt) / a batch file:
powershell.exe -c Start-Process cmd.exe -Verb RunAs ('/k {0} \"a\" \"B C\" \"d\"' -f ((Convert-Path 'TestEnv.cmd') -replace ' ', '^^ '))
Replace /k
with /c
to make the new window close automatically when the batch file exits.
The working directory for the batch file is C:\Windows\System32
.
If you also want to ensure that the batch file executes in the caller's current directory:
REM From cmd.exe (Command Prompt) / a batch file:
powershell.exe -c Start-Process cmd.exe -Verb RunAs ('/k cd \"{0}\" ^&^& {1} \"a\" \"B C\" \"d\"' -f $PWD.ProviderPath, ((Convert-Path 'TestEnv.cmd') -replace ' ', '^^ '))
Read on for an explanation.
The main problem is:
When you pass a batch-file path directly - as the executable - to Start-Process -Verb RunAs
, there seems to be a problem with passing an argument list that contains double quotes ("
) - I don't know the reason, but the problem occurs in a layer below PowerShell, either in the underlying System.Diagnostics.ProcessStartInfo
.NET API or possibly even in the underlying ShellExecuteExe
WinAPI function.
(If you either need no arguments or none of them require "
, you can pass the batch-file path directly as the executable; by default, because the underlying executable is cmd.exe
, which is located in C:\Windows\System32
, C:\Windows\System32
becomes the working directory, which you can override with -WorkingDirectory
, but note that you must then refer to the batch file with a (possibly relative) path, if it is located elsewhere.)
Workaround:
Instead of using the batch-file path directly as the executable to launch, use cmd.exe
as the executable, and pass the batch-file path and all its arguments as arguments to the /c
option (or /k
, if you want to keep the new window open).
Unfortunately, with -Verb Runas
, cmd.exe
invariably uses C:\Windows\System32
as the new process' working directory - passing a startup directory with the -WorkingDirectory
parameter is then ignored.
powershell.exe
, but, curiously, not to pwsh.exe
(PowerShell [Core] v6+) and .NET-based executables, which (a) preserve the caller's working directory by default and (b) do honor a -WorkingDirectory
argument.Therefore, if your TestEnv.cmd
batch file is located in the current directory - as opposed to a directory listed in the PATH
environment variable ($env:PATH
) - you must pass the batch file's full path to cmd.exe
, which you can determine with Convert-Path
.
Note: If you batch file is in the PATH
, so to speak, this step isn't necessary.
Unfortunately, another workaround is then needed, in case the batch file's full path contains spaces: Because "..."
-enclosing the batch-file path inexplicably fails, the individual spaces must be ^
-escaped instead.
From inside PowerShell this means your command must look like this (note that I'm using /k
to keep the new window open, for diagnostic purposes; use /c
to auto-close the window when the batch file exits):
# From inside PowerShell:
Start-Process cmd.exe -Verb RunAs (
'/k {0} "a" "B C" "d"' -f ((Convert-Path 'TestEnv.cmd') -replace ' ', '^ ')
)
Caveat: Since cmd.exe
is being invoked, C:\Windows\System32
is the working directory.
If you also want to ensure that the batch file executes in the caller's current directory, you must prepend a cd
command:
# From inside PowerShell:
Start-Process cmd.exe -Verb RunAs (
'/k cd "{0}" && {1} "a" "B C" "d"' -f $PWD.ProviderPath, ((Convert-Path 'TestEnv.cmd') -replace ' ', '^ ')
)
Calling this from cmd.exe
(Command Prompt) / a batch file, via Windows PowerShell's CLI, powershell.exe
(note that in PowerShell [Core] v6+ it is now pwsh
), adds additional complexity:
The "
chars. must be escaped as \"
so that PowerShell recognizes as them as part of the command to execute rather than as syntactic quoting around the CLI arguments.
^
must be escaped as ^^
and, in the second command below, &
as ^&
to prevent cmd.exe
from interpreting these characters (up front).
REM From cmd.exe (Command Prompt) / a batch file:
powershell.exe -c Start-Process cmd.exe -Verb RunAs ('/k {0} \"a\" \"B C\" \"d\"' -f ((Convert-Path 'TestEnv.cmd') -replace ' ', '^^ '))
If you also want to ensure that the batch file executes in the caller's current directory:
REM From cmd.exe (Command Prompt) / a batch file:
powershell.exe -c Start-Process cmd.exe -Verb RunAs ('/k cd \"{0}\" ^&^& {1} \"a\" \"B C\" \"d\"' -f $PWD.ProviderPath, ((Convert-Path 'TestEnv.cmd') -replace ' ', '^^ '))