This is a rather advanced script, in that it's got a fair number of moving parts, and functions it supports.
I created it specifically with "flexibility" and "multiple options for using it" in mind. There should be little to no need to edit the script itself by anyone wishing to use it. The script has built in prompts for specific input so that it can complete it's work.
What this script does:
- Automates the changing of Local user account passwords on Windows based computers.
- Windows 2000 and higher systems are supported.
- Can process through a manually provided list of computers, dump lists of computers from Active directory, or can target specific stand alone systems.
- When processing through a list of computers, all actions successful, or not, are logged to paths you provide.
- You can specify the user account name you wish to update, (the script prompts for input here) won't force you to update the "administrator" account only.
Requirements for running:
- Administrative privileges are required for all systems you wish to attempt to change password data on.
- Support for the AD powershell module should exist already on the system you execute this script from. (if pulling a list of computers to process from AD).
Considerations for using:
- This is an "active system" script. So when using it, it will only be able to perform updates against computers that are online (and reachable) at the time of it's use.
- All systems which can't be reached will be written out to a log.
- The Log created for "compsnotonline" can be used at another time to try updating missed systems.
- An AD domain OU with approx 400 workstations spread across a WAN took 30 - 45 minutes to run.
- Carefully read all prompts, and follow the provided directions within the script while using it.
- Note that at this time no logs are generated when choosing to target single machines.
- This script has been successfully run against a production domain on multiple occasions. But as with anything found on the internet. USE AT YOUR OWN RISK . . TEST TEST TEST.
------------------------------------------Begin Script------------------------------------------------
cls
echo " "
echo " "
write-host "This script will help you change passwords for computer based user accounts." -foregroundcolor Yellow
echo " "
write-host "You will be given several options for how to proceed.`nPlease read and respond to each question carefully." -foregroundcolor Yellow
echo " "
write-host "All script actions are logged.`nYou will be prompted for where the logs will be written to." -foregroundcolor Yellow
echo " "
write-host "You can EXIT this script at any time by using the 2 keys CTRL and C`nand then typeing Y to exit." -foregroundcolor RED
echo " "
Read-host "Press enter to continue:"
cls
echo " "
write-host "Would you like to update an account password on a list of computers?`nOr would you like to update an account password on a single machine?" -foregroundcolor "Green"
echo " "
$1stChoice = read-host "Type list or single:"
If ($1stChoice -eq "single")
{
$Loop = "1"
While ($Loop -eq "1")
{
cls
$SingleComp = read-host "Type the computer name to be updated:"
$Account = read-host "Type the account name to be updated:"
$password = read-host "Type the new password:"
cls
([adsi]"WinNT://$SingleComp/$Account").SetPassword("$password")
If ($? -eq "True")
{
echo " "
write-host "Password change successful" -foregroundcolor Green
echo " "
}
ELSE
{
echo " "
write-host "Password change failed" -foregroundcolor Red
echo " "
}
echo " "
echo " "
write-host "Would you like to process another system?" -foregroundcolor Yellow
$LoopBack = read-host "Type Y or N:"
If ($Loopback -eq "y")
{
$Loop = "1"
}
ELSE
{
$Loop = "2"
}
}
echo " "
cls
write-host "You have selected to not update anymore passwords." -foregroundcolor Yellow
write-host "Have a good day" -foregroundcolor Yellow
read-host "Press enter to exit:"
}
ELSE
{
cls
echo " "
write-host "You have chosen to perform updates on a list of computers." -foregroundcolor Yellow
echo " "
write-host "Would you like to import a text file list of computers?`nOr import a list of systems from Active Directory?" -foregroundcolor Yellow
echo " "
$2ndChoice = read-host "Type AD or Txt:"
IF ($2ndChoice -eq "AD")
{
cls
write-host "Please provide the location for all script output.`nWith this script always define a path with a subfolder for your root path.`nFor example 'c:\scriptdata'." -foregroundcolor Red
echo " "
write-host "The folders you specify 'do not have to exist in advance'.`nThey will be created automatically by the script." -foregroundcolor red
echo " "
write-host "Failure to follow these directions `nwill cause all script output to fail to be written." -foregroundcolor red
echo " "
$RootDrv = read-host "Type the desired base drive letter to be used, 'example C, or D, or G', 'DO NOT INCLUDE A ':' :"
$RD = $RootDrv + ':' + '\'
$OutputPath = read-host "Type a folder name that will be created at the root of your drive letter:"
$Output = $RD + $OutputPath
$CompsNotOnline="$Output\CompsNotOnline.txt"
$PasswordChangeFailed="$Output\PasswordChangeFailed.txt"
$Success="$Output\PasswordChanged.txt"
$TXT="$Output\ADComps.txt"
If (!(Test-Path -Path $Output ))
{
new-item -path $RD -name $OutputPath -type directory -force
}
ELSE
{
Remove-item $TXT -erroraction silentlycontinue
Remove-item $CompsNotOnline -erroraction silentlycontinue
Remove-item $PasswordChangeFailed -erroraction silentlycontinue
Remove-item $Success -erroraction silentlycontinue
}
import-module ActiveDirectory
cls
write-host "Please type the fully qualified LDAP path you'd like to process.`nAll OU's under the path specified will be processed" -foregroundcolor Yellow
write-host "For example, if your domain is named Bob.fred.com,`nand you want to process computers from an OU called Computers" -foregroundcolor Yellow
write-host "You would type = OU=Computers,DC=Bob,DC=fred,DC=com" -foregroundcolor Yellow
echo " "
$Ldap = read-host "Ldap Path:"
get-adcomputer -filter * -properties * -SearchBase $Ldap| sort Name | Select-Object Name >>$TXT
(gc $TXT | select -Skip 3) | sc $TXT
$Lines = (gc $TXT)
$Lines | ForEach-Object { $_.TrimEnd(); } | Out-File $TXT -Encoding Ascii
echo " "
Write-host "Gathering list of computers..."
echo " "
Timeout /t 10 /nobreak
cls
$Computers = (gc $TXT)
$UserName = read-host "Type the user name to update:"
$password = read-host "Type the new password:"
cls
echo " "
Write-host "Script is ready to begin processing the computer list`nto update the password for the user $Username..." -foregroundcolor "Green"
Read-host "Press Enter to Begin:"
cls
ForEach ($Computer in $Computers)
{
get-wmiobject -computer $Computer Win32_group -erroraction silentlycontinue | out-null
If ($? -eq "True")
{
echo " "
write-host "$Computer is online"
([adsi]"WinNT://$Computer/$UserName").SetPassword("$password")
If ($? -eq "True")
{
echo " "
write-host "Password changed for $Username on $Computer" -foregroundcolor "Green"
echo "Password changed for $Username on $Computer" >>$Success
}
ELSE
{
echo " "
write-host "Password change for $Username on $Computer failed" -foregroundcolor "Red"
echo "$Computer" >>$PasswordChangeFailed
}
}
ELSE
{
echo " "
write-host "There was a problem contacting $Computer" -foregroundcolor RED
echo " "
write-host "Adding machine name to CompsNotOnline.txt under $Output" -foregroundcolor RED
echo "$Computer" >>$CompsNotOnline
}
}
cls
echo " "
Write-host "The selected systems with the user account $UserName`nhave been updated with the new password $password. Please update your records." -foregroundcolor Cyan
read-host "Press enter to exit:"
}
ELSE
{
cls
write-host "Please provide the location for all script output.`nWith this script always define a path with a subfolder for your root path.`nFor example 'c:\scriptdata'." -foregroundcolor Red
echo " "
write-host "The folders you specify 'do not have to exist in advance'.`nThey will be created automatically by the script." -foregroundcolor red
echo " "
write-host "Failure to follow these directions `nwill cause all script output to fail to be written." -foregroundcolor red
echo " "
$RootDrv = read-host "Type the desired base drive letter to be used, 'example C, or D, or G', 'DO NOT INCLUDE A ':' :"
$RD = $RootDrv + ':' + '\'
$OutputPath = read-host "Type a folder name that will be created at the root of your drive letter:"
$Output = $RD + $OutputPath
$CompsNotOnline="$Output\CompsNotOnline.txt"
$PasswordChangeFailed="$Output\PasswordChangeFailed.txt"
$Success="$Output\PasswordChanged.txt"
$TXT="$Output\ADComps.txt"
If (!(Test-Path -Path $Output ))
{
new-item -path $RD -name $OutputPath -type directory -force
}
ELSE
{
Remove-item $TXT -erroraction silentlycontinue
Remove-item $CompsNotOnline -erroraction silentlycontinue
Remove-item $PasswordChangeFailed -erroraction silentlycontinue
Remove-item $Success -erroraction silentlycontinue
}
echo " "
Write-Host "Select TXT file of systems to update..." -ForegroundColor yellow
function Read-OpenFileDialog([string]$WindowTitle, [string]$InitialDirectory, [string]$Filter = "All files (*.*)|*.*", [switch]$AllowMultiSelect)
{
Add-Type -AssemblyName System.Windows.Forms
$openFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$openFileDialog.Title = $WindowTitle
if ($InitialDirectory -eq $Null) { $openFileDialog.InitialDirectory = $InitialDirectory }
$openFileDialog.Filter = $Filter
if ($AllowMultiSelect) { $openFileDialog.MultiSelect = $true }
$openFileDialog.ShowHelp = $true # Without this line the ShowDialog() function may hang depending on system configuration and running from console vs. ISE.
$openFileDialog.ShowDialog() > $null
if ($AllowMultiSelect) { return $openFileDialog.Filenames } else { return $openFileDialog.Filename }
}
$var = Read-OpenFileDialog("Select list of systems to process...:","C:\")
$Lines = (gc $var)
$Lines | ForEach-Object { $_.TrimEnd(); } | Out-File $var -Encoding Ascii
$Computers = (gc $var)
cls
echo " "
$UserName = read-host "Type the user name to update:"
echo " "
$password = read-host "Type the new password:"
cls
Write-host "Script is ready to begin processing the computer list`nto update the password for the user $Username..." -foregroundcolor "Green"
Read-host "Press Enter to Begin:"
cls
ForEach ($Computer in $Computers)
{
get-wmiobject -computer $Computer Win32_group -erroraction silentlycontinue | out-null
If ($? -eq "True")
{
echo " "
write-host "$Computer is online"
([adsi]"WinNT://$Computer/$UserName").SetPassword("$password")
If ($? -eq "True")
{
echo " "
write-host "Password changed for $Username on $Computer" -foregroundcolor "Green"
echo "Password changed for $Username on $Computer" >>$Success
}
ELSE
{
echo " "
write-host "Password change for $Username on $Computer failed" -foregroundcolor "Red"
echo "$Computer" >>$PasswordChangeFailed
}
}
ELSE
{
echo " "
write-host "There was a problem contacting $Computer" -foregroundcolor RED
echo " "
write-host "Adding machine name to CompsNotOnline.txt under $Output" -foregroundcolor RED
echo "$Computer" >>$CompsNotOnline
}
}
cls
echo " "
Write-host "The selected systems with the user account $UserName`nhave been updated with the new password $password. Please update your records." -foregroundcolor Cyan
read-host "Press enter to exit:"
}
}
--------------------------------End Script--------------------------------------------------
No comments:
Post a Comment