Changing passwords is always one of those fun tasks for any admin. It becomes even more challenging when your a Windows admin over hundreds of individual servers that are not part of the same domain. Here’s my take on a PowerShell script to change the password of a local user on a remote system (or many remote systems), regardless of domain status.
I like to take the opportunity to use vSphere as a way to gather systems to run scripts against as opposed to the traditional serverlist.txt files. This lets me target systems to run scripts against via any grouping provided by vSphere including folders, hosts, clusters, datacenters, etc. My favorite is the use of folders as many folks already use these to group common systems together. Note you can always use the ‘VM’ folder which is the (hidden) root folder which holds all VMs if you want to take it that far.
So we’ll connect to vCenter via PowerCli and grab a list of Powered On Windows systems. Next comes connecting to each system via WMI and changing the password. Two sets of credentials are required, one used to connect to the remote system and the second being the account being updated (Note these can be the same account – you can logon as bob and change bob’s password).
In the script you will notice a -flush parameter. This helps resolve the “Multiple connections to a server or shared resource by the same user, using more than one user name, are not allowed. Disconnect all previous connections to the server or shared resource and try again.” issue. Be aware that the -flush switch will remove all mapped drives and connections to all remote systems by simply running – net use * /d /y
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# ChangePwd | |
# | |
# Author: Shawn Masterson | |
# Created: June 2013 | |
# Version: 1 | |
# | |
# Purpose: Change local Windows account passwords on remote systems located in a vSphere folder | |
# | |
# | |
# Arguments: | |
# -vCenter – vCenter Server FQDN or IP | |
# -VMFolder – vCenter folder containing VMs to update | |
# -Flush – Clears current share connections (\\computer\share$) | |
# | |
# Examples: | |
# .\ChangePwd.ps1 | |
# .\ChangePwd.ps1 -Flush | |
# .\ChangePwd.ps1 -vCenter vcenterserver -VMFolder "My VMs" | |
# | |
# Notes: | |
# You can right click on script and 'Run from Powershell' | |
# The -Flush parameter will run the following command on start-up – net use * /d /y (understand what this does before using!) | |
# If you have multiple folders with the same name, VMs in all folders will be updated | |
# | |
# Supported OS's: | |
# Windows Servers 03/03×64/08/08×64/08R2/2012 | |
# | |
# Requirements: | |
# vCenter (Server list to be updated is gathered from vCenter – only tested on 5.x) | |
# Script host must have PowerCLI (only tested on 5.x) | |
# Script host needs WMI/RPC access to servers being updated | |
# VMware Tools must be installed and running on the Windows VMs | |
# Must be able to resolve DNS names of systems as seen in vCenter | |
# | |
# Disclaimer: | |
# There is absolutely zero error catching built into this script! | |
# USE AT YOUR OWN RISK | |
# | |
# | |
# | |
#——————————————————————– | |
# Parameters (Arguments) | |
# | |
param ( | |
$vcenter, | |
$VMFolder, | |
[switch]$Flush | |
) | |
# | |
# | |
#——————————————————————– | |
# User Denifed Variables | |
# | |
# vSphere folder to exclude (notmatch) | |
$skipFolder = "Clone" | |
# | |
#——————————————————————– | |
# Load Snap-ins | |
# | |
# Add VMware snap-in if required | |
if ( (Get-PSSnapin -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue) -eq $null ) {add-pssnapin VMware.VimAutomation.Core} | |
# | |
# | |
#——————————————————————– | |
# Main Procedures | |
# | |
# Flush share connections if -Flush is used | |
If ($Flush) {net use * /d /y | Out-Null} | |
# | |
cls | |
Write-Host "ChangePwd " (Get-Date) -foregroundcolor "Yellow" | |
Write-Host "`nThis script will change the password of a user account on remote VMs" -foregroundcolor "Yellow" | |
Write-Host "VMs are gathered from a choosen vSphere folder`n`n`n" -foregroundcolor "Yellow" | |
# | |
# Ask for vCenter address (if not provided) | |
If ($vcenter -eq $Null) {$vcenter = Read-Host "Enter vCenter server FQDN or IP"} | |
Write-Host | |
# | |
# Connect to vCenter server | |
Try | |
{ | |
Write-Host "Connecting to vCenter -" $vcenter -foregroundcolor "Yellow" | |
Connect-VIServer $vcenter -EA Stop | |
} | |
Catch | |
{ | |
Write-Host "`r`n`r`nUnable to connect to" $vcenter -backgroundcolor Red | |
Write-Host "Exiting…`r`n`r`n" -foregroundcolor "Yellow" | |
Exit | |
} | |
# | |
# Ask for vSphere folder to get VMs from (if not provided) | |
Write-Host "`n" | |
If ($VMFolder -eq $Null) {$VMFolder = Read-Host "Enter vSphere folder to query"} | |
# | |
# Grab all Windows VM guest hostnames that are Powered On in the supplied vSphere folder | |
Write-Host "`n" | |
Write-Host "Querying All Running Windows VMs in Folder(s) -" $VMFolder -foregroundcolor "Yellow" | |
$vms = Get-Folder $VMFolder | Get-VM | Where-Object {$_.Guest.OSFullName -like "*Windows*" -and $_.PowerState -eq "PoweredOn" -and $_.Folder.Name -notmatch $skipFolder} | ` | |
Sort -Property Name | foreach { $_.Guest.Hostname } | |
# | |
# Confirm vSphere Folder exists | |
If ($vms -eq $Null) { | |
Write-Host "`r`n`r`nFolder does not exists or no VMs in Folder to scan" -backgroundcolor Red | |
Write-Host "Exiting…`r`n`r`n" -foregroundcolor "Yellow" | |
Exit} | |
# | |
Write-Host "`nFound" $vms.Count "systems`n" -foregroundcolor "Yellow" | |
# | |
# | |
Write-Host "`n`n" | |
If ($Account -eq $Null) {$Account = Read-Host "Enter Windows account to update password"} | |
If ($Newpwd -eq $Null) {$Newpwd = Read-Host 'Enter NEW password for' $Account} | |
# | |
# | |
# | |
Write-Host "`n`n" | |
Write-Host "Credentials are needed to connect to the Windows Servers being updated`n" -foregroundcolor "Yellow" | |
If ($Username -eq $Null) {$Username = Read-Host "Enter Windows Admin username"} | |
If ($Password -eq $Null) {$Password = Read-Host 'Enter Windows password for' $Username} | |
Write-Host "`n`n" | |
Write-Host "Process started…" -foregroundcolor "Yellow" | |
Write-Host | |
# | |
# | |
# Update account password on each VM | |
foreach ($vm in $vms) { | |
Write-Host "`nUpdating" $vm -foregroundcolor "Yellow" | |
Try { | |
$remote = New-Object System.DirectoryServices.DirectoryEntry("WinNT://$vm/$account,user",$username,$password) | |
$remote.SetPassword($Newpwd) | |
} | |
Catch { | |
Write-Host "FAILED" -backgroundcolor Red | |
$error[0] | |
$fails = $fails + "`n" + $vm | |
} | |
} | |
# | |
# | |
# | |
# | |
#——————————————————————– | |
# Close Connections | |
# | |
# Disconnect vCenter | |
Disconnect-VIServer -Server $vcenter -Force -Confirm:$false | |
# | |
#——————————————————————– | |
# Outputs | |
# | |
Write-Host "`n`n" | |
Write-Host "Update Complete`n" -foregroundcolor "Yellow" | |
If ($fails -ne $Null) {Write-Host "The following servers failed to update:" $fails -backgroundcolor Red} | |
# | |
# Prompt to exit script | |
Write-Host "`n`n" | |
Write-Host "Press any key to continue …" | |
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") |