Reputation: 24269
I'm writing a configuration script that has to do a few things that require UAC approval, and I was hoping ideally to achieve approximating "$session = sudo -v" so that I can mix elevated/non-elevated and not require the user to sit at the screen for the 15-30 minutes setup takes just in-case it needs another approval.
Ideally, I'm trying to avoid opening a new console/terminal window since this both loses output and causes screen-flashing that could be problematic for some of my users.
Which suggests that what I may want to do is Start-Job with a credential so that I can wait for completion and retrieve the output.
So now I have two problems:
My attempts to use a ScriptBlock failed because of the need to multiply-escape strings that are going into a ScriptBlock construction:
{ [System.Environment]::SetEnvironmentVariable("TEST", "OK", "Machine") }
fails for me when I try to pass it to Start-Process -verb runAs powershell -ArgumentList @('-NoLogo', '-NoProfile', '-Command', $ScriptBlock)
:
At line:1 char:46
+ [System.Environment]::SetEnvironmentVariable(TEST, OK, Machine)
+ ~
Missing ')' in method call.
At line:1 char:46
+ [System.Environment]::SetEnvironmentVariable(TEST, OK, Machine)
+ ~~~~
Unexpected token 'TEST' in expression or statement.
At line:1 char:50
+ [System.Environment]::SetEnvironmentVariable(TEST, OK, Machine)
+ ~
Missing argument in parameter list.
At line:1 char:63
+ [System.Environment]::SetEnvironmentVariable(TEST, OK, Machine)
+ ~
Unexpected token ')' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MissingEndParenthesisInMethodCall
or if I try to use System.Diagnostics.Process
.
Upvotes: 1
Views: 415
Reputation: 440132
No, there is no way to cache a UAC confirmation, unfortunately.
Invocation with elevation requires the use of Start-Process
, with -Verb RunAs
, and Start-Process
fundamentally only supports string arguments (a process command line).
A string that is to be passed to the PowerShell CLI's (possibly positionally implied) -Command
/ -c
parameter requires "
chars. that are to be preserved as part of the command being passed to be escaped as \"
(see this answer for an explanation); applied to your call:
Start-Process -Verb RunAs powershell -ArgumentList @(
'-NoLogo',
'-NoProfile',
'-Command',
"`"$($ScriptBlock -replace '"', '\"')`""
)
Caveat: While passing the pass-through arguments individually to -ArgumentList
, as above, may be conceptually preferable, a long-standing bug unfortunately makes it better to encode all arguments in a single string - see this answer; the bug is also the reason for enclosing the -Command
argument explicitly in (outer, unescaped) embedded "
above; while it'll typically work without that, it prevents runs of multiple spaces from getting folded into a single space, which could matter in embedded string literals.
Upvotes: 2