I have a simple script to create a scheduled task like this:
$action = New-ScheduledTaskAction -Execute "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -Argument '-file "File.ps1"'
$trigger = New-ScheduledTaskTrigger -AtStartup
Register-ScheduledTask -Action $action -Trigger $trigger -TaskPath "Tasks" -TaskName "Name" -Description "Description" -User Admin -Password $password -RunLevel Highest
how can I prompt for UAC and capture the password that user enters in the UAC prompt as $password variable to be used in the script?
Use Get-Credential
to ask for the target user's credentials, which returns a [pscredential]
instance.
.GetNetworkCredential().Password
on it in order to obtain the plain-text representation of the password stored in that [pscredential]
object.Register-ScheduledTask
does require passing a plain-text password.Verifying that the credentials are (a) valid in principle (i.e. that the username / password combination is correct) and (b) are capable of running with elevation requires additional work.
(a) can be achieved via the Test-WinCredential
helper function from this MIT-licensed Gist
Assuming you've looked at the linked source code to ensure that it is safe, you can directly download and define it in the current session as follows (instructions on how to make it available in future sessions will print):
irm https://gist.github.com/mklement0/83e8e6a2b39ecec7b0a14a8e631769ce/raw/Test-WinCredential.ps1 | iex
(b) can be achieved by checking whether the specified credentials refer to a user in the local Administrators
group, using Get-LocalGroupMember
. I think that that implies having the permission to run with elevation - do tell me if I'm wrong.
Note:
# Prompt for an administrator's credentials and verify that they are valid.
do {
$cred = Get-Credential -Message 'Please specify an administrator''s credentials: '
if (-not $cred) { Write-Warning 'Aborted by user request.'; exit 2 }
if (-not (Test-WinCredential $cred)) {
Write-Warning "The specified username-password combination isn't valid. Please try again."
}
elseif (-not (Get-LocalGroupMember -ErrorAction Ignore Administrators $cred.UserName)) {
Write-Warning "User $($cred.UserName) is not a member of the local Administrators group. Please try again."
} else {
break # OK
}
} while ($true)
# $cred.UserName now contains the username.
# Obtain the password as plain text.
# Note: This should generally be avoided.
$plainTextPassword = $cred.GetNetworkCredential().Password