I have a script here that reads a list of desktops and changes the administrator password of those desktops. It works but I have a minor problem. Once the error shows up in Powershell, the value is never reset. So for example the second DT failed and the third and fourth DT succeeds. Under the error column, it'll show the second DT's error even though the password change was successful. However, it works fine on the output file (outputs.txt). I tried $error.clear() but it didn't solve my problem. Maybe I put it in the wrong place? I'd appreciate if you can help me with this as I am 99.9% done. Thank you.
[cmdletbinding()]
param (
[parameter(mandatory = $true)]
$InputFile,
$OutputDirectory
)
#Log failures in an output file called "outputs.txt" stored in the directory of input file
if(!$outputdirectory) {
$outputdirectory = (Get-Item $InputFile).directoryname
}
$failedcomputers = Join-Path $outputdirectory "outputs.txt"
$stream = [System.IO.StreamWriter] $failedcomputers
$stream.writeline("ComputerName `t IsOnline `t PasswordChangeStatus `t Error")
$stream.writeline("____________ `t ________ `t ____________________ `t _____")
#Prompt to confirm password twice and read password in a secure manner
$password = Read-Host "Enter the password" -AsSecureString
$confirmpassword = Read-Host "Confirm the password" -AsSecureString
#Convert password into plain text for comparison
$pwd1_text = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($password))
$pwd2_text = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($confirmpassword))
#If the passwords don't match, script exits; otherwise, it continues.
if($pwd1_text -ne $pwd2_text) {
Write-Error "Entered passwords are not same. Script is exiting."
exit
}
#Check if input file exists. If file not found, script exits.
if(!(Test-Path $InputFile)) {
Write-Error "File ($InputFile) not found. Script is exiting."
exit
}
#Read contents of input file using Get-Content cmdlet and store list in an array called $computers
$Computers = Get-Content -Path $InputFile
#Loop through each computer account in the array and check if online or not using Test-Connection cmdlet
foreach ($Computer in $Computers) {
$Computer = $Computer.toupper()
$Isonline = "OFFLINE"
$Status = "SUCCESS"
Write-Verbose "Working on $Computer"
if((Test-Connection -ComputerName $Computer -count 1 -ErrorAction 0)) {
$Isonline = "ONLINE"
Write-Verbose "`t$Computer is Online"
} else { Write-Verbose "`t$Computer is OFFLINE" }
#If ping is successful, password is changed
try {
$account = [ADSI]("WinNT://$Computer/Administrator,user")
$account.psbase.invoke("setpassword",$pwd1_text)
Write-Verbose "`tPassword Change completed successfully"
}
#If password change fails, respective error is recorded
catch {
$status = "FAILED"
Write-Verbose "`tFailed to Change the administrator password. Error: $_"
$e = $_.Exception
$errmsg = $e.Message
while ($e.InnerException) {
$e = $e.InnerException
$errmsg = $e.Message
}
}
$obj = New-Object -TypeName PSObject -Property @{
ComputerName = $Computer
IsOnline = $Isonline
PasswordChangeStatus = $Status
Error = $errmsg
}
$obj | Select ComputerName, IsOnline, PasswordChangeStatus, Error
if($Status -eq "FAILED" -or $Isonline -eq "OFFLINE") {
$stream.writeline("$Computer `t`t $isonline `t`t $status `t $errmsg")
}else{
$stream.writeline("$Computer `t`t $isonline `t`t $status")
}
}
$stream.close()
Write-Host "`n`nFailed computers list is saved to $failedcomputers"
$errmsgis the problem? Why not just throw in aClear-Variable errmsgat the end of the loop$errmsgvariable at the beginning of the foreach loop just like the other variables.$errmsg = ""