I am learning PowerShell to write tools for my team. I was in a pinch today and got this working, but I want to streamline it by removing the IF statements in the ForEach loop, since the only difference between the commands is the parameter -replace or -remove.
Write-Host "This script removes or replaces en masse users' msds-SyncServerURL property"
DO {
$TargetSSU=Read-Host "`nWhat msds-SyncServerURL do you want to replace or remove?"
$UsersToBeFixed=Get-ADUser -Filter {msds-SyncServerURL -like $TargetSSU} -Properties ('name','samaccountname','msDS-SyncServerURL')
IF ($UsersToBeFixed -eq $null) {
Write-Host "`nNo users appear to have $TargetSSU as their msds-SyncServerURL value. Please try again."
}
} UNTIL ($UsersToBeFixed -ne $null)
Write-Host "`n`nThe following users have $TargetSSU as their msds-SyncServerURL value:"
$UsersToBeFixed |select name,samaccountname,msds-syncserverurl|ft
DO {
$Action=Read-Host "Do you want to [R]emove or [U]pdate $TargetSSU?"
} Until (($Action -eq "R") -or ($Action -eq "U"))
IF ($Action -eq "U") {
DO {
$NewSyncServer=Read-Host "`nEnter the new Sync Server's hostname (not the URL)"
Write-Host "`nChecking to see if $NewSyncServer has a userfile share..."
$VerifySyncServer=Test-Path \\$NewSyncServer\userfiles
IF ($VerifySyncServer -eq $false) {
Write-host "`n$NewSyncServer does not appear to be a valid Sync Server hostname. Please try again."
}
} UNTIL ($VerifySyncServer -eq $true)
$TargetSSU="https://$NewSyncServer.ourdomain.com"
}
ForEach ($userToBeFixed in $UsersToBeFixed) {
Write-Host "`nFixing" ($usertobefixed).name
IF ($Action -eq "R") {
Set-ADObject -identity $userToBeFixed -remove @{"msDS-SyncServerUrl" = $TargetSSU}
}
IF ($Action -eq "U") {
Set-ADObject -identity $userToBeFixed -replace @{"msDS-SyncServerUrl" = $TargetSSU}
}
}
Write-Host "`nHere is the result of the operation:"
foreach ($userToBeFixed in $UsersToBeFixed) {
Get-ADUser -Identity $userToBeFixed -Properties ('name','samaccountname','msDS-SyncServerURL')|select name,samaccountname,msds-syncserverurl
}
I initially had the following switch in place, trying various permutations of quotation marks and even {$action="replace"}:
Switch($action)
{
R {'remove'}
U {'replace'}
}
I also tried Invoke-Expression in the ForEach loop:
$CMD="Set-ADObject -identity $userToBeFixed -$action @{`"msDS-SyncServerUrl`" = $TargetSSU}"
Invoke-Expression -Command $CMD
Invariably, the Set-ADObject cmdlet would fail, typically complaining about Set-ADObject not being able to find positional parameters that accepts arguments like '-remove', 'System.Object[]' or 'System.Collections.Hashtable'.
I isolated the issue to the Set-ADObject not liking the $action variable being used as a parameter. If I replaced -$action with -replace or -remove it would work (as it is in the above code snippet).
I realize this is a minor issue, but it bothers me to have such redundant code for seemingly no reason. I would love to learn how to work around this.
Also, unrelated, I haven't really found a better way to do this:
Until (($Action -eq "R") -or ($Action -eq "U"))
I have searched and tried other solutions like:
Until ($Action -eq @{"R" -or "U"})
But can't seem to consolidate the evaluation of multiple conditions. This bothers me, but not as much as my main question here.
Please go easy on me. I'm new to this whole thing. If anyone sees anything else I can improve let me know. I want to learn this.
Thanks.