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?
CodePudding user response:
Use
Get-Credential
to ask for the target user's credentials, which returns a[pscredential]
instance.- You can then call
.GetNetworkCredential().Password
on it in order to obtain the plain-text representation of the password stored in that[pscredential]
object. - To be clear, for security reasons this is generally to be avoided; however,
Register-ScheduledTask
does require passing a plain-text password.
- You can then call
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 GistAssuming 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, usingGet-LocalGroupMember
. I think that that implies having the permission to run with elevation - do tell me if I'm wrong.
Note:
- I've only tested the following in a local, non-domain environment.
- Tweaks may be needed for domain environments
# 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