I have script that (that I tweaked from a forum) that reads a text file which contains usernames.
This generates a 9 character random password and outputs the password via PowerShell:
$ListOfUsers = Get-Content C:\temp\list.txt
foreach ($user in $ListOfUsers) {
#Generate a 9-character random password
$Password = -join ((33..126) | Get-Random -Count 9 | ForEach-Object { [char]$_ })
#Convert the password to secure string
$Pass = ConvertTo-SecureString $Password -AsPlainText -Force
#Reset the account password
Set-ADAccountPassword $user -NewPassword $Pass -Reset
#Display userid and password values
Write-Host $user, $Password
}
Since the password it displays contains special characters - this cause problems for certain users who access access special pieces of equipment on our network, I am forced to set random password manually in AD for these users.
I was wondering if it is possible to define a random password that contains letters (lower and higher case) and numbers only?
OR
Could I supply a text file with passwords on each line for PowerShell to set for each user?
UPDATE 1
@Theo I ran your code and got this error:
PS C:\Windows\system32> $ListOfUsers = Get-Content C:\temp\list.txt
$result = foreach ($user in $ListOfUsers) {
#Generate a 9-character random password
$Password = New-Password -TotalLength 9 -Symbols 0
#Convert the password to secure string
$Pass = ConvertTo-SecureString $Password -AsPlainText -Force
#Reset the account password
Set-ADAccountPassword $user -NewPassword $Pass -Reset
#Display userid and password values
#Write-Host $user, $Password
# or better yet, output the newly set passwords as PsCustomObject to use in a csv file
[PsCustomObject]@{User = $user; Password = $Password}
}
# show on screen
$result | Format-Table -AutoSize
# write to CSV file you can open in Excel by double-clicking it
$result | Export-Csv -Path 'C:\temp\NewPasswords.csv' -NoTypeInformation -UseCulture
New-Password : The term 'New-Password' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a
path was included, verify that the path is correct and try again.
At line:4 char:17
+ $Password = New-Password -TotalLength 9 -Symbols 0
+ ~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (New-Password:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
ConvertTo-SecureString : Cannot bind argument to parameter 'String' because it is null.
At line:6 char:36
+ $Pass = ConvertTo-SecureString $Password -AsPlainText -Force
+ ~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [ConvertTo-SecureString], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ConvertToSecureStringCommand
Please enter the desired password for 'CN=Test User,CN=Users,DC=my,DC=domain,DC=net'
Password:
Seem like New-Password is not available on my PowerShell.
Unless you can see something I can't?
UPDATE 2
@Theo ran it your script with changes (removed the symbols) got this error message:
PS C:\Windows\system32> function New-Password {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[ValidateRange(8, 128)]
[int]$TotalLength = 9,
[int]$LowerAlpha = 3,
[int]$UpperAlpha = 4,
[int]$Digits = 2
)
# check if the given parameters are => 0 and <= $TotalLength
$LowerAlpha = [math]::Max(0,[math]::Min($LowerAlpha, $TotalLength))
$UpperAlpha = [math]::Max(0,[math]::Min($UpperAlpha, $TotalLength))
$Digits = [math]::Max(0,[math]::Min($Digits, $TotalLength))
if ($TotalLength - ($LowerAlpha + $UpperAlpha + $Digits) -lt 0) {
throw "Too many alphas, digits or symbols to fit the total password length"
}
$list = [System.Collections.Generic.List[char]]::new()
if ($LowerAlpha) { $list.AddRange([char[]]([char[]]'abcdefghijklmnopqrstuvwxyz' | Get-Random -Count $LowerAlpha)) }
if ($UpperAlpha) { $list.AddRange([char[]]([char[]]'ABCDEFGHIJKLMNOPQRSTUVWXYZ' | Get-Random -Count $UpperAlpha)) }
if ($Digits) { $list.AddRange([char[]]([char[]]'0123456789' | Get-Random -Count $Digits)) }
($list | Sort-Object {Get-Random}) -join ''
}
$ListOfUsers = Get-Content C:\temp\list.txt
$result = foreach ($user in $ListOfUsers) {
#Generate a 9-character random password
$Password = New-Password -TotalLength 9 -Symbols 0
#Convert the password to secure string
$Pass = ConvertTo-SecureString $Password -AsPlainText -Force
#Reset the account password
Set-ADAccountPassword $user -NewPassword $Pass -Reset
#Display userid and password values
#Write-Host $user, $Password
# or better yet, output the newly set passwords as PsCustomObject to use in a csv file
[PsCustomObject]@{User = $user; Password = $Password}
}
# show on screen
$result | Format-Table -AutoSize
# write to CSV file you can open in Excel by double-clicking it
$result | Export-Csv -Path 'C:\temp\NewPasswords.csv' -NoTypeInformation -UseCulture
New-Password : A parameter cannot be found that matches parameter name 'Symbols'.
At line:31 char:45
+ $Password = New-Password -TotalLength 9 -Symbols 0
+ ~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [New-Password], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,New-Password
ConvertTo-SecureString : Cannot bind argument to parameter 'String' because it is null.
At line:33 char:36
+ $Pass = ConvertTo-SecureString $Password -AsPlainText -Force
+ ~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [ConvertTo-SecureString], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ConvertToSecureStringCommand
Please enter the desired password for 'CN=Test User,CN=Users,DC=my,DC=domain,DC=net'
Password:
I even removed changed this line from this:
+ $Password = New-Password -TotalLength 9 -Symbols 0
To this:
+ $Password = New-Password
Got this error then:
PS C:\Windows\system32> function New-Password {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[ValidateRange(8, 128)]
[int]$TotalLength = 9,
[int]$LowerAlpha = 3,
[int]$UpperAlpha = 4,
[int]$Digits = 2
)
# check if the given parameters are => 0 and <= $TotalLength
$LowerAlpha = [math]::Max(0,[math]::Min($LowerAlpha, $TotalLength))
$UpperAlpha = [math]::Max(0,[math]::Min($UpperAlpha, $TotalLength))
$Digits = [math]::Max(0,[math]::Min($Digits, $TotalLength))
if ($TotalLength - ($LowerAlpha + $UpperAlpha + $Digits) -lt 0) {
throw "Too many alphas, digits or symbols to fit the total password length"
}
$list = [System.Collections.Generic.List[char]]::new()
if ($LowerAlpha) { $list.AddRange([char[]]([char[]]'abcdefghijklmnopqrstuvwxyz' | Get-Random -Count $LowerAlpha)) }
if ($UpperAlpha) { $list.AddRange([char[]]([char[]]'ABCDEFGHIJKLMNOPQRSTUVWXYZ' | Get-Random -Count $UpperAlpha)) }
if ($Digits) { $list.AddRange([char[]]([char[]]'0123456789' | Get-Random -Count $Digits)) }
($list | Sort-Object {Get-Random}) -join ''
}
$ListOfUsers = Get-Content C:\temp\list.txt
$result = foreach ($user in $ListOfUsers) {
#Generate a 9-character random password
$Password = New-Password
#Convert the password to secure string
$Pass = ConvertTo-SecureString $Password -AsPlainText -Force
#Reset the account password
Set-ADAccountPassword $user -NewPassword $Pass -Reset
#Display userid and password values
#Write-Host $user, $Password
# or better yet, output the newly set passwords as PsCustomObject to use in a csv file
[PsCustomObject]@{User = $user; Password = $Password}
}
# show on screen
$result | Format-Table -AutoSize
# write to CSV file you can open in Excel by double-clicking it
$result | Export-Csv -Path 'C:\temp\NewPasswords.csv' -NoTypeInformation -UseCulture
Method invocation failed because [System.Collections.Generic.List`1[[System.Char, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]] does
not contain a method named 'new'.
At line:19 char:5
+ $list = [System.Collections.Generic.List[char]]::new()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
You cannot call a method on a null-valued expression.
At line:21 char:24
+ if ($LowerAlpha) { $list.AddRange([char[]]([char[]]'abcdefghijklmnopqrstuvwx ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At line:22 char:24
+ if ($UpperAlpha) { $list.AddRange([char[]]([char[]]'ABCDEFGHIJKLMNOPQRSTUVWX ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At line:23 char:24
+ if ($Digits) { $list.AddRange([char[]]([char[]]'0123456789' | Get-Random ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
ConvertTo-SecureString : Cannot bind argument to parameter 'String' because it is an empty string.
At line:33 char:36
+ $Pass = ConvertTo-SecureString $Password -AsPlainText -Force
+ ~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [ConvertTo-SecureString], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ConvertToSecureStringCommand
Please enter the desired password for 'CN=Test User,CN=Users,DC=my,DC=domain,DC=net'
Password:
Seems like the issue is on this line:
$list = [System.Collections.Generic.List[char]]::new()
UPDATE 3
I tried all your code without any changes and got this error message:
PS C:\Windows\system32> function New-Password {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[ValidateRange(8, 128)]
[int]$TotalLength = 10,
[int]$LowerAlpha = 3,
[int]$UpperAlpha = 2,
[int]$Digits = 3,
[int]$Symbols = 2
)
# check if the given parameters are => 0 and <= $TotalLength
$LowerAlpha = [math]::Max(0,[math]::Min($LowerAlpha, $TotalLength))
$UpperAlpha = [math]::Max(0,[math]::Min($UpperAlpha, $TotalLength))
$Digits = [math]::Max(0,[math]::Min($Digits, $TotalLength))
$Symbols = [math]::Max(0,[math]::Min($Symbols, $TotalLength))
if ($TotalLength - ($LowerAlpha + $UpperAlpha + $Digits + $Symbols) -lt 0) {
throw "Too many alphas, digits or symbols to fit the total password length"
}
$list = [System.Collections.Generic.List[char]]::new()
# older PowerShell versions use: $list = New-Object System.Collections.Generic.List[char]
if ($LowerAlpha) { $list.AddRange([char[]]([char[]]'abcdefghijklmnopqrstuvwxyz' | Get-Random -Count $LowerAlpha)) }
if ($UpperAlpha) { $list.AddRange([char[]]([char[]]'ABCDEFGHIJKLMNOPQRSTUVWXYZ' | Get-Random -Count $UpperAlpha)) }
if ($Digits) { $list.AddRange([char[]]([char[]]'0123456789' | Get-Random -Count $Digits)) }
if ($Symbols) { $list.AddRange([char[]]([char[]]'!@#$%^&*()_-+=[{]};:<>|./?~' | Get-Random -Count $Symbols)) }
($list | Sort-Object {Get-Random}) -join ''
}
$ListOfUsers = Get-Content C:\temp\list.txt
$result = foreach ($user in $ListOfUsers) {
#Generate a 9-character random password
$Password = New-Password -TotalLength 9 -Symbols 0
#Convert the password to secure string
$Pass = ConvertTo-SecureString $Password -AsPlainText -Force
#Reset the account password
Set-ADAccountPassword $user -NewPassword $Pass -Reset
#Display userid and password values
#Write-Host $user, $Password
# or better yet, output the newly set passwords as PsCustomObject to use in a csv file
[PsCustomObject]@{User = $user; Password = $Password}
}
# show on screen
$result | Format-Table -AutoSize
# write to CSV file you can open in Excel by double-clicking it
$result | Export-Csv -Path 'C:\temp\NewPasswords.csv' -NoTypeInformation -UseCulture
Method invocation failed because [System.Collections.Generic.List`1[[System.Char, mscorlib, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089]]] does not contain a method named 'new'.
At line:21 char:5
+ $list = [System.Collections.Generic.List[char]]::new()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
You cannot call a method on a null-valued expression.
At line:24 char:24
+ if ($LowerAlpha) { $list.AddRange([char[]]([char[]]'abcdefghijklmnopqrstuvwx ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At line:25 char:24
+ if ($UpperAlpha) { $list.AddRange([char[]]([char[]]'ABCDEFGHIJKLMNOPQRSTUVWX ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At line:26 char:24
+ if ($Digits) { $list.AddRange([char[]]([char[]]'0123456789' | Get-Random ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
ConvertTo-SecureString : Cannot bind argument to parameter 'String' because it is an empty string.
At line:37 char:36
+ $Pass = ConvertTo-SecureString $Password -AsPlainText -Force
+ ~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [ConvertTo-SecureString], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ConvertToSecureStringCommand
Please enter the desired password for 'CN=Test User,CN=Users,DC=my,DC=domain,DC=net'
Password:
You could use below helper function to generate passwords with or without special characters:
function New-Password {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[ValidateRange(8, 128)]
[int]$TotalLength = 10,
[int]$LowerAlpha = 3,
[int]$UpperAlpha = 2,
[int]$Digits = 3,
[int]$Symbols = 2
)
# check if the given parameters are => 0 and <= $TotalLength
$LowerAlpha = [math]::Max(0,[math]::Min($LowerAlpha, $TotalLength))
$UpperAlpha = [math]::Max(0,[math]::Min($UpperAlpha, $TotalLength))
$Digits = [math]::Max(0,[math]::Min($Digits, $TotalLength))
$Symbols = [math]::Max(0,[math]::Min($Symbols, $TotalLength))
if ($TotalLength - ($LowerAlpha + $UpperAlpha + $Digits + $Symbols) -lt 0) {
throw "Too many alphas, digits or symbols to fit the total password length"
}
$list = [System.Collections.Generic.List[char]]::new()
# older PowerShell versions use: $list = New-Object System.Collections.Generic.List[char]
if ($LowerAlpha) { $list.AddRange([char[]]([char[]]'abcdefghijklmnopqrstuvwxyz' | Get-Random -Count $LowerAlpha)) }
if ($UpperAlpha) { $list.AddRange([char[]]([char[]]'ABCDEFGHIJKLMNOPQRSTUVWXYZ' | Get-Random -Count $UpperAlpha)) }
if ($Digits) { $list.AddRange([char[]]([char[]]'0123456789' | Get-Random -Count $Digits)) }
if ($Symbols) { $list.AddRange([char[]]([char[]]'!@#$%^&*()_-+=[{]};:<>|./?~' | Get-Random -Count $Symbols)) }
($list | Sort-Object {Get-Random}) -join ''
}
Usage:
Paste the function above on top of your script and then your code would become:
$ListOfUsers = Get-Content C:\temp\list.txt
$result = foreach ($user in $ListOfUsers) {
#Generate a 9-character random password
$Password = New-Password -TotalLength 9 -Symbols 0
#Convert the password to secure string
$Pass = ConvertTo-SecureString $Password -AsPlainText -Force
#Reset the account password
Set-ADAccountPassword $user -NewPassword $Pass -Reset
#Display userid and password values
#Write-Host $user, $Password
# or better yet, output the newly set passwords as PsCustomObject to use in a csv file
[PsCustomObject]@{User = $user; Password = $Password}
}
# show on screen
$result | Format-Table -AutoSize
# write to CSV file you can open in Excel by double-clicking it
$result | Export-Csv -Path 'C:\temp\NewPasswords.csv' -NoTypeInformation -UseCulture
As per your comment, here's a stripped-down version of the code, where the New-Password
function now only has one optional parameter: $TotalLength
.
It will only use uppercase and lowercase characters plus digits. No more symbols.
function New-Password {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[ValidateRange(8, 128)]
[int]$TotalLength = 10
)
# calculate the minimum number of characters (lower/upper and digits) needed:
# maximum in $TotalLength divided by 3 (rounded up)
$numChars = [int][math]::Ceiling($TotalLength / 3)
$list = New-Object System.Collections.Generic.List[char]
# PowerShell versions => 5 use:
# $list = [System.Collections.Generic.List[char]]::new()
while ($list.Count -lt $TotalLength) {
# add lower, upper characters and digits to the list
$list.AddRange([char[]]([char[]]'abcdefghijklmnopqrstuvwxyz' | Get-Random -Count $numChars))
$list.AddRange([char[]]([char[]]'ABCDEFGHIJKLMNOPQRSTUVWXYZ' | Get-Random -Count $numChars))
$list.AddRange([char[]]([char[]]'0123456789' | Get-Random -Count $numChars))
}
# return the randomized password
(($list | Sort-Object {Get-Random}) -join '').Substring(0, $TotalLength)
}
$ListOfUsers = Get-Content -Path 'C:\temp\list.txt'
$result = foreach ($user in $ListOfUsers) {
#Generate a 9-character random password
$Password = New-Password -TotalLength 9 # if you don't set the TotalLength it will default to 10
#Convert the password to secure string
$Pass = ConvertTo-SecureString $Password -AsPlainText -Force
#Reset the account password
Set-ADAccountPassword $user -NewPassword $Pass -Reset
# output the newly set passwords as PsCustomObject to use in a csv file
[PsCustomObject]@{User = $user; Password = $Password}
}
# show on screen
$result | Format-Table -AutoSize
# write to CSV file you can open in Excel by double-clicking it
$result | Export-Csv -Path 'C:\temp\NewPasswords.csv' -NoTypeInformation -UseCulture