Thursday, May 29, 2014

Change Local Account Password CmdLet

There are lots of ways to change the password on local machine accounts. I used this as a sample project as I was exploring all the features of CmdLets. At first glance, this code is overkill for the task at hand. It is a good example of how to implement -WhatIf, -Confirm, and -Force. I have another post that shows just the 2 lines of code needed to change the local account password.


#AccountManagement is used for Varifying password changes
Add-Type -AssemblyName System.DirectoryServices.AccountManagement

function Set-AccountPassword
{
<#
.Synopsis
   Sets the password for a local machine account
.DESCRIPTION
   It will set a password on a remote machine for the specified account with the specified password
.EXAMPLE
   Set-AccountPassword -ComputerName localhost -AccountName Administrator -Password BatteryStapleHorse
.EXAMPLE
    Set-AccountPassword -Password BatteryStapleHorse -SkipVerify -Force
#>
    [CmdletBinding(DefaultParameterSetName='Default', 
                  SupportsShouldProcess, 
                  PositionalBinding=$false,
                  HelpUri = 'http://www.microsoft.com/',
                  ConfirmImpact='Medium')]
    Param
    (
        # ComputerName help description
        [Parameter(Mandatory=$false, 
                   ValueFromPipeline=$true,
                   ValueFromPipelineByPropertyName=$true, 
                   Position=0)]
        [string]$ComputerName = "$env:computername",

        # AccountName help description
        [Parameter(Position=1)]
        [string]
        $AccountName = 'Administrator',

        # Password help description
        [Parameter(Position=2,
                    Mandatory=$true,
                    ParameterSetName="Default")]
        [ValidateLength(15,139)]
        [String]
        $Password,

        [Parameter()]
        [switch]$SkipVerify,

        [Parameter()]
        [switch]$Force
    )


    Begin
    {
     
    }   
    Process
    {
        Write-Verbose "Testing connection to $ComputerName before we try and change the password"
        if(Test-Connection $ComputerName -Count 1){
            Write-Verbose "$ComputerName is online"

            #Example of support for -WhatIf
            #Also used with -Confirm and ConfirmImpact options
            if ($pscmdlet.ShouldProcess("$ComputerName\$AccountName", "SetPassword"))
            {
                #Example of support for -Force, this will prompt every time unless the -force param is used
                if($Force -or $pscmdlet.ShouldContinue("Change the password for this account: $ComputerName\$AccountName","Setting Password")){
                    Write-Verbose "Using ADSI for connection to WinNT://$ComputerName/$AccountName"
                    $admin = [adsi]("WinNT://$ComputerName/$AccountName, user")

                    Write-Verbose "Invoking SetPassword on $ComputerName"
                    $admin.psbase.invoke("SetPassword", $Password)
                
                    # This will verify that the password was changed to $Password
                    # Skip Verify is an optional param
                    if(!$SkipVerify){
                        Write-Verbose "Verifing that the password changed correctly"
                        
                        $obj = New-Object System.DirectoryServices.AccountManagement.PrincipalContext('machine',"$ComputerName")
                        if($obj.ValidateCredentials("$AccountName","$Password")){
                            Write-Verbose "Verified!"
                        }else{
                            Write-Error "Failed to verify password change"
                        }
                    }else{
                        Write-Verbose "SkipVerify=True skipping verify check"
                    } #SkipVerify
                } #ShouldContinue
            } #ShouldProcess
        } #Test-Connection
    } #Process
    End
    {
    }
}

No comments: