Home > Enterprise >  How to prompt for UAC in PowerShell 7 and save the entered password as variable?
How to prompt for UAC in PowerShell 7 and save the entered password as variable?

Time:12-22

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.
  • 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:

  • 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
  • Related