1.問題
我有一個復雜的批處理檔案,其中某些部分需要以提升/管理員權限運行(例如與 Windows 服務互動),我找到了一種 Powershell 方法來做到這一點:
powershell.exe -command "try {$proc = start-process -wait -Verb runas -filepath '%~nx0' -ArgumentList '<arguments>'; exit $proc.ExitCode} catch {write-host $Error; exit -10}"
但有一個巨大的警告!我的腳本 ( ) 的提升實體以%~nx0環境變數的新副本開始,而我set "var=content"之前的所有內容都不可用。
2.到目前為止我嘗試過的
這個 Powershell 腳本也無濟于事,因為Verb = "RunAs"requires UseShellExecute = $truewhich 反過來又與/互斥StartInfo.EnvironmentVariables.Add()
$p = New-Object System.Diagnostics.Process
$p.StartInfo.FileName = "cmd.exe";
$p.StartInfo.Arguments = '/k set blasfg'
$p.StartInfo.UseShellExecute = $true;
$p.StartInfo.Verb = "RunAs";
$p.StartInfo.EnvironmentVariables.Add("blasfg", "C:\\Temp")
$p.Start() | Out-Null
$p.WaitForExit()
exit $p.ExitCode
即使這樣可行,我仍然需要傳輸數十個變數......
3. 沒有吸引力的半解決方案
因為規避問題不是正確的解決方案。
- helper tools like hstart - because I can't relay on external tools. Only CMD, Powershell and maybe VBscript (but it looks like
runaspluswaitanderrorlevel/ExitCodeprocessing isn't possible with/in vbs). - passing (only required) variables as arguments - because I need dozens and escaping them is an ugly chore (both the result and doing it).
- restarting the whole script - because it's inefficient with all the parsing, checking processing and other tasks happening again (and again and ...). I'd like to keep the elevated parts to a minimum and some actions can later be run as a normal user (e.g service start/stop).
- Writing the environment to a file and rereading it in the elevated instance - because it's an ugly hack and I'd hope there's a cleaner option out there. And writing possibly sensitive information to a file is even worse than storing it temporarily in an environment variable.
uj5u.com熱心網友回復:
這是使用以下方法的概念證明:
使
powershell呼叫呼叫另一個aux。powershell實體作為提升的目標行程。這允許外部實體將重新創建呼叫者的環境變數(外部實體繼承,因此可以用 列舉)的 陳述句
powershell“烘焙”到傳遞給 aux 的字串中。實體,然后重新呼叫原始批處理檔案。Set-ItemGet-ChilItem Env:-command
警告:此解決方案在提升的行程中盲目地重新創建呼叫者行程中定義的所有環境變數 - 考慮預過濾,可能通過名稱模式,例如通過共享前綴;例如,要將變數重新創建限制為名稱以 開頭的變數,請在下面的命令中foo替換Get-ChildItem Env:為。Get-ChildItem Env:foo*
@echo off & setlocal
:: Test if elevated.
net session 1>NUL 2>NUL && goto :ELEVATED
:: Set sample env. vars. to pass to the elevated re-invocation.
set foo1=bar
set "foo2=none done"
set foo3=3" of snow
:: " dummy comment to fix syntax highlighting
:: Re-invoke with elevation, synchronously, reporting the exit
:: code of the elevated run.
:: Two sample arguments, ... and "quoted argument" are passed on re-invocation.
powershell -noprofile -command ^
trap { [Console]::Error.WriteLine($_); exit -667 } ^
exit ( ^
Start-Process -Wait -PassThru -Verb RunAs powershell ^
"\" -noprofile -command `\" $(Get-ChildItem Env: | ForEach-Object { 'Set-Item \\\"env:' $_.Name '\\\" \\\"' $($_.Value -replace '\""', '`\\\""') '\\\"; ' }) cmd /c '\`\"%~f0\`\" ... \`\"quoted argument\`\" & exit'; exit `$LASTEXITCODE`\" \"" ^
).ExitCode
echo -- Elevated re-invocation exited with %ERRORLEVEL%.
:: End of non-elevated part.
exit /b
:ELEVATED
echo Now running elevated...
echo -- Arguments received:
echo [%*]
echo -- Env. vars. whose names start with "foo":
set foo
:: Determine the exit code to report.
set ec=5
echo -- Exiting with exit code
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/442155.html
標籤:powershell batch-file cmd admin elevation
上一篇:.bat檔案的條件執行
