28 Jan 2013

How To Change User Password With PowerShell

Easy ways to change or reset a user's local or domain account password using PowerShell.  You do not need any PowerShell modules.  Just built in PowerShell will be used to change the password.

Why do anything with PowerShell when you can already use CMD?

An important concept to grasp is the ability to reuse code and process multiple items.

"I can already use the NET USER command from CMD.  Why use PowerShell?"

We want to use PowerShell for 3 reasons:
  1. It's the new way.  PowerShell creator Jeffrey Snover is now the Lead Architect for Windows Server 8.  Him moving into a role of such importance is the exclamation point on what PowerShell people have been saying since it came out: "Start using it or start getting left behind!"
  2. Reusability.  Even though our simple task of changing a user's password should not be something that needs to be scripted, and then reused, it could be.  And anything you use with PowerShell can be.  It's definitely one of the important reasons we want to use PowerShell when we can.  You never know at the start of a project that you won't want to reuse some part of it on a later project.
  3. Write once, process many.  Once we've got a command to change a password, there's no reason we can't use that command on multiple objects.  It's easy, and that's philosophy is at the core of all automation.
Change every local user account on a computer to have the same password

Lets dive into an example to make a great point about the reusability and the ability to handle multiple password changes with a single command.

First, we need to get a list of users to change the passwords on.  We'll use WMI for this task.

A great thing about using WMI for this task is that it can be used remotely or locally.  If you want to run this on a remote computer (appropriately named "remote-pc") it's almost as easy – no extra setup required (firewall exceptions and RPC come in handy though.)

How To Get a List of Local User Accounts with PowerShell:

$userlist  = get-wmiobject win32_useraccount

How To Get a List of Local User Accounts from Remote Computer with PowerShell:

$remoteuserlist = get-wmiobject win32_useraccount –computername "remote-pc"
 
Change Password using ADSI object

Secondly, we'll look at how to change a password using the ADSI object in .NET.

To get the ADSI object for a user, we need the computer name that the local account belongs to, and the user account name.  One thing that we can use from the list of user accounts from WMI that we got with PowerShell is that the computer name and user account name are both listed in a property called "Caption".   Too bad the Caption property uses a backslash ("\") and ADSI uses a slash ("/").  To get around that, I will use the string method Replace().  That part looks like this:

$userlist[0].caption.replace("\","/")

There are several options for telling the ADSI class what kind of account to connect to.  Two of those I find : WinNT (for local accounts), and LDAP (for domain accounts).  Those are case sensitive. Since we're looking for a local account, it will be in this format:

[adsi]"WinNT://local-PC/accountname"

Retrieving a domain user account is just as easy.  It's in the form:


How to Set a Password For a User Account

There are two options for creating the user account object:  use it one time then it's gone, or save it as a variable.

If you're going to do a password reset, and will not be making any other changes, you can use this simple method of creating your user object instance.  Just use parentheses around the object, and this will ensure that the object is able to be referenced and methods can be run from it.  It looks like this:

([adsi]"WinNT://Remote-PC/AccountName").SetPassword("Shazbot!")

After this runs, the password for the account "Accountname" on the computer "Remote-PC" is set to "Shazbot!".  There is no further reference to the object in the script.

If you know the computer name, and the account name, this one liner will set your password:

([adsi]"WinNT://<Local or Remote Computer Name>/<Username>").SetPassword("<Password>")

On the other hand, if you're going to need to account for anything else, such as viewing or changing any other property on the account, then you should keep it as a variable.  It's very similar to the first method:

[adsi]$userVariable = "WinNT://<Local or Remote Computer Name>/<Username>"

Now you have a variable that represents the user account, and you can change the password using the same SetPassword() method used above.

$userVariable.SetPassword("Gilligan+Skipper=TrueLove4Ever")

How To Reset All Local User Accounts on a Computer to the Same Password

Here's a quick one-liner that sets all user accounts on a computer to have the same password.

Get-WmiObject win32_useraccount | Foreach-Object {([adsi]("WinNT://"+$_.caption).replace("\","/")).SetPassword("FluxCapacitor!11-5-1955")}
If that seems like gibberish to you, here's the translation:

Get the local user accounts from WMI, and since we're not done with those objects, they are passed through the pipeline.  They are the input for the Foreach-Object, which applies everything that's in the scriptblock to each individual user account.  When being passed through the scriptblock, individual user accounts are referenced by the "$_".  We build a string like "WinNT://computer/user" by switching the "\" symbol from the user accounts "caption" property into a "/" by the use of the string method Replace.  After the string is put together, [adsi] processes and creates an ADSI reference to the real user account on the computer.  The SetPassword method is called on the object, which sets the password to "FluxCapacitor!11-5-1955".  It performs that on each local user account, and then it's done.

No comments:

Post a Comment