PowerShell Force Password Change Multiple Users

PowerShell Force Password Change Multiple Users

Scenario:

A friend of mine told that he has a task to do and it will take time to perform it. I have asked him what is was it and he told me that he has to ensure that all users in his Active Directory need to change their password. He told me also that he wants to ensure that their password will expire and also the option for the user not to be able to change the password to be deactivated. He told me that he was going to do it manually for his users one by one or in small groups, such as Organizational Units. I told him to give me sometime to come up with a script to make his task easier and I wrote the below script. Let’s see what is included in the script in more details.

I had to deal with the three below options for the user as you can see in them in Active Directory Users and Computers:

User much change password at next logon

User cannot change password

Password never expires

What is does

In general the script is a able to force a single or multiple users to change their password at next logon. The script also ensures that the users is able to change password and that the password will expire based on company’s policies. The script is able to perform the above action on the whole domain, which is not recommended. You are able to specify an Organizational Unit or a single user.

[adinserter name=”In Article”]

Parameters

The script can accept two parameters, which will define as always the behavior of the script. The script can accept the below parameters:

OrganizationalUnit

User

-OrganizationalUnit

When the administrator runs the script with -OrganizationalUnit , it will run the changes only under the Organizational Unit you have specified. You can specify an Organizational Unit in the below format:

A distinguished name

A GUID (objectGUID)

A security identifier (objectSid)

A Security Account Manager account name (sAMAccountName)

Below is the part of the script that is related with -OrganizationalUnit parameter.

Code:

{($OrganizationalUnit -ne "") -and ($User -eq "")}{ $InputStatus = "Wrong" while ($InputStatus -eq "Wrong") { $UserInput = "" $AllUsersInfo = Write-Host "Are you sure that you want to force change password for ALL users under this Organizational Unit? [Yes/No] (Deafult: No): " -ForegroundColor Red -NoNewline $UserInput = Read-Host Switch -Regex ($UserInput){ {($UserInput -ieq "yes") -or ($UserInput -ieq "y")}{ Write-Host "Trying to get Organizational Unit details from Active Directory..." try{$OU = Get-ADOrganizationalUnit -Identity $OrganizationalUnit -ErrorAction Stop} catch{ Write-Warning "The script was not able to find the Organizational Unit" break} Write-Host "Organizational Unit details have been retrieved!!!" -ForegroundColor Green Write-Host "Retrieving users from Active Directory under" $OU.DistinguishedName try{$Users = Get-ADUser -Filter * -Properties * -SearchBase "$OU" -ErrorAction Stop} catch{ Write-Warning "The script was not able to retrieve the users under the Organizational Unit" break} If ($Users -ne $null){ Write-Host "Users Retrieved!!!" -ForegroundColor Green foreach ($User in $Users){ try{Set-ADUser -Identity $User -ChangePasswordAtLogon $true -CannotChangePassword $false -PasswordNeverExpires $false -ErrorAction Stop} catch{ Write-Warning "The script was not able to force password change for" $User.SamAccountName break} Write-Host "Password Change has been forced for" $User.SamAccountName -ForegroundColor Green } $InputStatus = "Correct" Break } else{ Write-Host "There are no users under" $OU.DistinguishedName Write-Host "Exiting..." $InputStatus = "Correct" Break } Break } {($UserInput -ieq "no") -or ($UserInput -ieq "n") -or ($UserInput -eq "")}{ Write-Host "Exiting..." $InputStatus = "Correct" Break } default { Write-Host "Your input is wrong. Please try again" $InputStatus = "Wrong";Break} } };Break }

The part of code above is part of a switch statement. First the script will ask the administraotr to confirm that he/she wants to run the changes for all users under the specific Organizational Unit. If the administrator will not confirm by providing “yes” or “y” (case insensitive) then the script will exit. The default answer is “no” in order to avoid any mistakes and perform any actions without the confirmation of the administrator. After the confirmation, the script will provide information to the administrator for the actions that is performing. First, it will try to get Organizational Unit details from Active Directory in order to ensure that the Organizational Unit exists. If the everything is fine with the Organizational Unit then it will retrieve all users under that Organizational Unit and will save them in a variable in order to use them later and ensure that there are users under it. If there are users under it, for every user in the list that has been retrieved, it will force user to change password at next logon, set the password to expire and enable user to change the password. For every user the script will confirm that the change has been applied and when it will finish the array it will exit.

[adinserter name=”In Article”]

-User

When the administrator will run the script with -User parameter, the script will force password change on the specific user only. The administrator can provide the user in the below formats:

A distinguished name

A GUID (objectGUID)

A security identifier (objectSid)

A SAM account name (sAMAccountName)

Below is the part of the script that is related to -User parameter.

Code:

{($OrganizationalUnit -eq "") -and ($User -ne "")}{ Write-Host "Trying to get user details from Active Directory..." try{$ADUser = Get-ADUser -Identity $User -ErrorAction Stop} catch{ Write-Warning "The script was not able to retrieve user details for" $User break} Write-Host "Details for" $ADUser.SamAccountName "has been retrieved from Active Directory" -ForegroundColor Green try{Set-ADUser -Identity $ADUser -ChangePasswordAtLogon $true -CannotChangePassword $false -PasswordNeverExpires $false -ErrorAction Stop} catch{ Write-Warning "The script was not able to force password change for" $User.SamAccountName break} Write-Host "Password Change has been forced for" $ADUser.SamAccountName -ForegroundColor Green;Break }

The part of code above is part of a switch statement. The script first will try to get the user details from Active Directory in order to ensure that everything is OK with the value provided by the administrator. If the retrieval of details is successful, then it will force user to change password at next logon, set the password to expire and enable user to change the password. After that the script will inform the administrator that has competed the change and will exit.

[adinserter name=”In Article”]

Without Parameter

The administrator can run the script without any parameters. If the script is run without any parameters, then it will try to perform the changes on all users under the domain. Please avoid using the script without any parameters as this is dangerous for your systems. If you run the script against all users under the domain, the script cannot distinguish service accounts, application accounts and any other user accounts that are used by your systems. If you perform the changes on that type of user accounts also then it will affect your systems.

Below is the part of the script that is related on running the script without any parameters.

Code:

{($OrganizationalUnit -eq "") -and ($User -eq "")}{ $InputStatus = "Wrong" While ($InputStatus -eq "Wrong") { $Caution = @" CAUTION CAUTION CAUTION It is dangerous to force password change on ALL user objects under the domain. "@ Write-Host $Caution -ForegroundColor Red $AllUsersInfo = Write-Host "Are you sure that you want to force change password for ALL user objects in Active Directory? [Yes/No] (Deafult: No): " -ForegroundColor Red -NoNewline $UserInput = Read-Host Switch -Regex ($UserInput){ {($UserInput -ieq "yes") -or ($UserInput -ieq "y")}{ Write-Host "Retrieving Domain..." try{$Domain = (Get-ADDomain -ErrorAction Stop).DistinguishedName} catch{ Write-Warning "The script was not able to retrieve the domain" break} Write-Host "Domain has been retrieved!!!" -ForegroundColor Green Write-Host "Retrieving all users from Active Directory..." try{$Users = Get-ADUser -Filter * -Properties * -SearchBase "$Domain" -ErrorAction Stop} catch{ Write-Warning "The script was not able to retrieve the users inthe domain." break} foreach ($User in $Users){ try{Set-ADUser -Identity $User -ChangePasswordAtLogon $true -CannotChangePassword $false -PasswordNeverExpires $false -ErrorAction Stop} catch{ Write-Warning "The script was not able to force password change for" $User.SamAccountName break} Write-Host "Password Change has been forced for" $User.SamAccountName -ForegroundColor Green} $InputStatus = "Correct" Break } {($UserInput -ieq "no") -or ($UserInput -ieq "n") -or ($UserInput -eq "")}{ $InputStatus = "Correct" Write-Host "Exiting..." Break } default { Write-Host "Your input is wrong. Please try again." -ForegroundColor Red $InputStatus = "Wrong";Break } } };Break }

The part of code above is part of a switch statement. The script firstly, will provide a caution message to the user that what is trying to do is dangerous. Then the script will ask the administrator to confirm that he /she wants to perform such action. The action follow, are similar to the actions taken when you are specifying an Organizational Unit. The default answer of the prompt is “no”. If the administrator will reply “no or “n” (case insensitive) the script will not perform any action and will exit. If the administrator will answer “yes” or “y” (case insensitive) then the script will retrive domain details. After that the script will retrieve all users in the domain and keep them in an array. At the end the script will process the array, it will force each user to change password at next logon, set the password to expire and enable user to change the password. After that the script will inform the administrator that has competed the change. For every user the script will confirm that the change has been applied and when it will finish the array it will exit.

You can download the script here or copy it from below. (Note that code within the script might not be copied correctly due to syntax highlighting.)

Hope you like it.

You feedback is appreciated.

If you have any questions or anything else please let me know in the comments below.

[adinserter name=”In Article”]

Related Links:

Solution / Script:

<# .SYNOPSIS Name: Force-PasswordChange.ps1 The purpose of this script is to force users under specific Organizational Unit to change their password .DESCRIPTION This is a script that you provide the Organizational Unit in Active Directory, that you need to force your users to change their password. It removes the option for the password not to expire, enabled the option of the user to force him / her to change the password the next time it will login. .RELATED LINKS Home .PARAMETER OrganizationalUnit In this parameter you need to specify the DistinguishedName of an Organizational Unit in order to force password change for the users under that Organizational Unit only. .PARAMETER User For this parameters you need to specify the SamAccountName of a user in your Active Directory to force password change only to that user. .NOTES Version: 1.0 Release Date: 06-03-2018 Author: Stephanos Constantinou .EXAMPLE Run the script against the entire domain. Force-PasswordChange.ps1 Run the script for specific Organizational Unit Force-PasswordChange.ps1 -OrganizationalUnit "OU=Accounting Users,DC=domain,DC=COM" Run the script for specific user Force-PasswordChange -User "stephanos" #> Param( [string]$OrganizationalUnit = "", [string]$User = "" ) $ErrorActionPreference = 'Stop' Import-Module ActiveDirectory cd ad: Switch -Regex ($OrganizationalUnit , $Users){ {($OrganizationalUnit -ne "") -and ($User -eq "")}{ $InputStatus = "Wrong" while ($InputStatus -eq "Wrong") { $UserInput = "" $AllUsersInfo = Write-Host "Are you sure that you want to force change password for ALL users under this Organizational Unit? [Yes/No] (Deafult: No): " -ForegroundColor Red -NoNewline $UserInput = Read-Host Switch -Regex ($UserInput){ {($UserInput -ieq "yes") -or ($UserInput -ieq "y")}{ Write-Host "Trying to get Organizational Unit details from Active Directory..." try{$OU = Get-ADOrganizationalUnit -Identity $OrganizationalUnit -ErrorAction Stop} catch{ Write-Warning "The script was not able to find the Organizational Unit" break} Write-Host "Organizational Unit details have been retrieved!!!" -ForegroundColor Green Write-Host "Retrieving users from Active Directory under" $OU.DistinguishedName try{$Users = Get-ADUser -Filter * -Properties * -SearchBase "$OU" -ErrorAction Stop} catch{ Write-Warning "The script was not able to retrieve the users under the Organizational Unit" break} If ($Users -ne $null){ Write-Host "Users Retrieved!!!" -ForegroundColor Green foreach ($User in $Users){ try{Set-ADUser -Identity $User -ChangePasswordAtLogon $true -CannotChangePassword $false -PasswordNeverExpires $false -ErrorAction Stop} catch{ Write-Warning "The script was not able to force password change for" $User.SamAccountName break} Write-Host "Password Change has been forced for" $User.SamAccountName -ForegroundColor Green } $InputStatus = "Correct" Break } else{ Write-Host "There are no users under" $OU.DistinguishedName Write-Host "Exiting..." $InputStatus = "Correct" Break } Break } {($UserInput -ieq "no") -or ($UserInput -ieq "n") -or ($UserInput -eq "")}{ Write-Host "Exiting..." $InputStatus = "Correct" Break } default { Write-Host "Your input is wrong. Please try again" $InputStatus = "Wrong";Break} } };Break } {($OrganizationalUnit -eq "") -and ($User -ne "")}{ Write-Host "Trying to get user details from Active Directory..." try{$ADUser = Get-ADUser -Identity $User -ErrorAction Stop} catch{ Write-Warning "The script was not able to retrieve user details" break} Write-Host "Details for" $ADUser.SamAccountName "has been retrieved from Active Directory" -ForegroundColor Green try{Set-ADUser -Identity $ADUser -ChangePasswordAtLogon $true -CannotChangePassword $false -PasswordNeverExpires $false -ErrorAction Stop} catch{ Write-Warning "The script was not able to force password change for" $User.SamAccountName break} Write-Host "Password Change has been forced for" $ADUser.SamAccountName -ForegroundColor Green;Break } {($OrganizationalUnit -eq "") -and ($User -eq "")}{ $InputStatus = "Wrong" While ($InputStatus -eq "Wrong") { $Caution = @" CAUTION CAUTION CAUTION It is dangerous to force password change on ALL user objects under the domain. "@ Write-Host $Caution -ForegroundColor Red $AllUsersInfo = Write-Host "Are you sure that you want to force change password for ALL user objects in Active Directory? [Yes/No] (Deafult: No): " -ForegroundColor Red -NoNewline $UserInput = Read-Host Switch -Regex ($UserInput){ {($UserInput -ieq "yes") -or ($UserInput -ieq "y")}{ Write-Host "Retrieving Domain..." try{$Domain = (Get-ADDomain -ErrorAction Stop).DistinguishedName} catch{ Write-Warning "The script was not able to retrieve the domain" break} Write-Host "Domain has been retrieved!!!" -ForegroundColor Green Write-Host "Retrieving all users from Active Directory..." try{$Users = Get-ADUser -Filter * -Properties * -SearchBase "$Domain" -ErrorAction Stop} catch{ Write-Warning "The script was not able to retrieve the users inthe domain." break} foreach ($User in $Users){ try{Set-ADUser -Identity $User -ChangePasswordAtLogon $true -CannotChangePassword $false -PasswordNeverExpires $false -ErrorAction Stop} catch{ Write-Warning "The script was not able to force password change for" $User.SamAccountName break} Write-Host "Password Change has been forced for" $User.SamAccountName -ForegroundColor Green} $InputStatus = "Correct" Break } {($UserInput -ieq "no") -or ($UserInput -ieq "n") -or ($UserInput -eq "")}{ $InputStatus = "Correct" Write-Host "Exiting..." Break } default { Write-Host "Your input is wrong. Please try again." -ForegroundColor Red $InputStatus = "Wrong";Break } } };Break } default {"Something went wrong. Please run the script again and check the values you have entered";Break} }

[adinserter name=”Matched-Content”]