Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
790 views
in Technique[技术] by (71.8m points)

passing quoted arguments from batch file to `powershell start` - self-elevation on demand

I am writing a Windows batch file that automatically escalates itself to administrative permissions, provided the user clicks "Yes" on the User Access Control dialog that appears.

I am using a technique I learned here to detect whether we already have admin rights and another from here to escalate. When appropriate, the following script, let's call it foo.bat, re-launches itself via a powershell-mediated call to runas:

@echo off
net session >NUL 2>NUL
if %ERRORLEVEL% NEQ 0 (
powershell start -wait -verb runas "%~dpfx0" -ArgumentList '%*'
goto :eof
)

echo Now we are running with admin rights
echo First argument is "%~1"
echo Second argument is "%~2"
pause

My problem is with escaping quotes in the -ArgumentList. The code above works fine if I call foo.bat one two from the command prompt, but not if one of the arguments contains a space, for example as in foo.bat one "two three" (where the second argument should be two words, "two three").

If I could even just get the appropriate behavior when I replace %* with static arguments:

powershell start -wait -verb runas "%~dpfx0" -ArgumentList 'one "two three"'

then I could add some lines in foo.bat that compose an appropriately-escaped substitute for %*. However, even on that static example, every escape pattern I have tried so far has either failed (I see Second argument is "two" rather than Second argument is "two three") or caused an error (typically Start-Process: A positional parameter cannot be found that accepts argument 'two'). Drawing on the docs for powershell's Start-Process I have tried all manner of ridiculous combinations of quotes, carets, doubled and tripled quotes, backticks, and commas, but there's some unholy interaction going on between batch-file quoting and powershell quoting, and nothing has worked.

Is this even possible?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
  • You've run into a perfect storm of two quoting hells (cmd and PowerShell), garnished with a PowerShell bug (as of PowerShell Core 6.2.0).

  • To work around the bug, the batch file cannot be reinvoked directly and must instead be reinvoked via cmd /c.

  • LotPings' helpful answer, which takes that into account, typically works, but not in the following edge cases:

    • If the batch file's full path contains spaces (e.g., c:pathomy batch file.cmd)
    • If the arguments happen to contain any of the following cmd metacharacters (even inside "..."): & | < > ^; e.g., one "two & three"
    • If the reinvoked-with-admin-privileges batch file relies on executing in the same working directory it was originally called from.

The following solution addresses all these edge cases. While it is far from trivial, it should be reusable as-is:

@echo off
setlocal

:: Test whether this invocation is elevated (`net session` only works with elevation).
:: If already running elevated (as admin), continue below.
net session >NUL 2>NUL && goto :elevated

:: If not, reinvoke with elevation.
set args=%*
if defined args set args=%args:^=^^%
if defined args set args=%args:<=^<%
if defined args set args=%args:>=^>%
if defined args set args=%args:&=^&%
if defined args set args=%args:|=^|%
if defined args set "args=%args:"=""%"
powershell -NoProfile -ExecutionPolicy Bypass -Command ^
  " Start-Process -Wait -Verb RunAs -FilePath cmd -ArgumentList "/c "" cd /d ""%CD%"" ^&^& ""%~f0"" %args% "" " "
exit /b

:elevated
:: =====================================================
:: Now we are running elevated, in the same working dir., with args passed through.
:: YOUR CODE GOES HERE.

echo First argument is "%~1"
echo Second argument is "%~2"

pause

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...