简体   繁体   中英

powershell.exe start-process -About "\" when using the Verb option

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\" \"BC\" \"d\"' -Verb Open

(b) Does not start after UAC confirmation.
powershell.exe start-process -FilePath 'TestEnv.cmd' -ArgumentList '\"a\" \"BC\" \"d\"' -Verb RunAs

(c) It is possible to invoke it, but the "BC" argument is not reflected in the "double quotes" argument, and "BC" is recognized separately.
powershell.exe start-process -FilePath 'TestEnv.cmd' -ArgumentList '"a" "BC" "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.

    • The same applies to 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 ' ', '^^ '))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM