Powershell: Working with Passwords
When creating a new Active Directory user from the command line in PowerShell, you will likely find yourself using Read-Host's -AsSecureString switch when entering the password.
1$password = Read-Host "Enter password" -AsSecureString
Next, you'll probably look around the Internets for a few hours or so trying to figure out how to change the password of the newly created user. You will soon discover that the user creation process in PowerShell 1.0 isn't very straightforward and it even requires a specific order for proper account creation. First, you create the account, then you set some basic properties, next you call SetInfo(), and finally you invoke setPassword using the following syntax:
1$newUser.psbase.Invoke("SetPassword", $password)
Now you may find yourself with the following exception: Exception calling "Invoke" with "2" argument(s): "Exception has been thrown by the target of an invocation." Originally, this post mentioned using toString() to address the problem but PowerShell team member Lee Holmes wrote to let me know that the password was changed literally to System.Security.SecureString. He also said that "there is no really easy way to convert a secure string to plain text - on purpose. Since a SecureString is supposed to prevent plain text from littering your computer's memory, converting it to plain text defeats the purpose."
My primary reason for using asSecureString is to encode the string into asterisks when typing it at the prompt. So Lee gave me two ways to convert the password to be used while invoking SetPassword. Note that unless you are using a secure LDAP channel, the password will be sent over the network in clear text.
1$temporaryCredential = New-Object System.Management.Automation.PsCredential "None", $password
2$newUser.psbase.Invoke("SetPassword", $temporaryCredential.GetNetworkCredential().Password)
Or, alternatively:
1$temporaryCredential = [Runtime.InteropServices.Marshal]::PtrToStringAuto(
2 [Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)
3)
4$newUser.psbase.Invoke("SetPassword", $temporaryCredential)
If you continue to see this exception, check to make sure that the password you entered meets your domain's password complexity requirements.
Update (2025): Security guidance and tooling have evolved since this 2007 post.
- SecureString does not provide encryption at rest or in transit and is no longer recommended as a secrets protection mechanism on its own. Prefer using
PSCredential, the SecretManagement module with a vault, and always use LDAPS/SSL or a secure API when setting passwords. - In modern environments with the ActiveDirectory module, prefer cmdlets that handle password setting for you, such as
Set-ADAccountPasswordorReset-ADAccountPassword, which accept aSecureStringfor-NewPasswordand take care of the necessary conversion.- Set-ADAccountPassword docs: https://learn.microsoft.com/powershell/module/activedirectory/set-adaccountpassword
- About SecureString conversion: https://learn.microsoft.com/powershell/module/microsoft.powershell.security/convertfrom-securestring
The original guidance above remains accurate for classic ADSI workflows; these notes are provided to help readers choose safer modern options when available.