Private/Undo-UserManipulation.ps1
|
function Undo-UserManipulation { param( [Parameter(Mandatory)] [string]$SearchBase, [Parameter(Mandatory)] [string]$Server, [Parameter(Mandatory)] [string]$TickValue, [ValidateRange(1, 100)] [int]$ThrottleLimit = 10 ) $CurrentFunction = Get-FunctionName Write-Log -Message "### Start Function $CurrentFunction ###" $StartRunTime = (Get-Date).ToString($Script:DateFormatLog) #################### main code | out- host ##################### $users = Get-ADUser ` -Filter "*" ` -SearchBase $SearchBase ` -Server $Server ` -Properties CanonicalName, SID, adminDescription, whenChanged, pwdLastSet, enabled | Where-Object { $_.adminDescription -eq $TickValue } $total = $users.Count if ($total -eq 0) { Invoke-Output -Type Warning -Message "No disabled users found for tick '$TickValue' under $SearchBase" return } else { $previewCount = [Math]::Min(20, $users.Count) $users | Get-Random -Count $previewCount | Select-Object SID, CanonicalName, Enabled, @{ Name = 'whenChanged' Expression = { if ($null -eq $_.whenChanged) { 'n/a' } else { ([DateTime]$_.whenChanged).ToString('yyyy-MM-dd HH:mm:ss') } } }, @{ Name = 'pwdLastSet' Expression = { if ($null -eq $_.pwdLastSet -or [Int64]$_.pwdLastSet -le 0) { 'never' } else { [DateTime]::FromFileTime([Int64]$_.pwdLastSet).ToString('yyyy-MM-dd HH:mm:ss') } } } | Format-Table | Out-Host } return $cname = Convert-FromDNToCN -DistinguishedName $SearchBase Invoke-Output -Type Quit -Message "Press 'Q' at any time to abort Undo User Manipulation`n for '$total' users under '$cname' with tick '$TickValue'" $startTime = Get-Date # LDAP worker to re-enable user without ADWS dependency $undoWorker = { $dn = $_.DistinguishedName $sid = $_.SID.Value $canonical = $_.CanonicalName $srv = $using:Server $errorMsg = $null try { $entry = New-Object System.DirectoryServices.DirectoryEntry "LDAP://$srv/$dn" $uac = [int]$entry.Properties["userAccountControl"].Value $entry.Properties["userAccountControl"].Value = ($uac -band (-bnot 2)) $entry.CommitChanges() $entry.Dispose() } catch { $errorMsg = $_.Exception.InnerException.Message if ([string]::IsNullOrWhiteSpace($errorMsg)) { $errorMsg = $_.Exception.Message } } [PSCustomObject]@{ User = "$canonical ($sid)" Success = [string]::IsNullOrWhiteSpace($errorMsg) Errors = $errorMsg } } $job = $users | ForEach-Object -Parallel $undoWorker -ThrottleLimit $ThrottleLimit -AsJob $allResults = [System.Collections.Generic.List[object]]::new() $processed = 0 $progressTick = 0 $pulseChars = @('|', '/', '-', '\\') while ($job.State -eq "Running") { if ([Console]::KeyAvailable) { if ([Console]::ReadKey($true).Key -eq 'Q') { Stop-Job $job break } } $newResults = Receive-Job $job if ($null -ne $newResults) { foreach ($r in @($newResults)) { $allResults.Add($r) } } $processed = $allResults.Count $elapsed = (Get-Date) - $startTime $rate = if ($elapsed.TotalSeconds -gt 0) { [math]::Round($processed / $elapsed.TotalSeconds, 2) } else { 0 } $eta = if ($rate -gt 0) { [math]::Round(($total - $processed) / $rate, 1) } else { 0 } $pulse = $pulseChars[$progressTick % $pulseChars.Count] $progressTick++ $percent = [math]::Round(($processed / $total) * 100, 2) Write-Progress ` -Activity "Undo User Manipulation (Enable users)" ` -Status "$pulse Done: $processed/$total | $rate ops/s | ETA: $eta s | Throttle: $ThrottleLimit" ` -PercentComplete $percent Start-Sleep -Milliseconds 250 } $remainingResults = Receive-Job $job if ($null -ne $remainingResults) { foreach ($r in @($remainingResults)) { $allResults.Add($r) } } Remove-Job $job -Force Write-Progress -Activity "Undo User Manipulation (Enable users)" -Completed $succeeded = $allResults | Where-Object { $_.Success -eq $true } $failed = $allResults | Where-Object { $_.Success -eq $false } if ($succeeded) { Invoke-Output -Type TextMaker -Message "Successfully re-enabled $($succeeded.Count) users under $cname`:" -TM $($succeeded.Count) } if ($failed) { Invoke-Output -Type Warning -Message "$($failed.Count) user(s) failed to re-enable:" $failed | ForEach-Object { Invoke-Output -Type Bullet -Message "$($_.User): $($_.Errors)" } } Invoke-Output -Type Success -Message "Finished Undo User Manipulation for tick '$TickValue'." ######################## main code ############################ $runtime = Get-RunTime -StartRunTime $StartRunTime Write-Log -Message " Run Time: $runtime [h] ###" Write-Log -Message "### End Function $CurrentFunction ###" } |