Private/Helpers/Invoke-ADRetrievalWithProgress.ps1
|
function Invoke-ADRetrievalWithProgress { [CmdletBinding()] param( [Parameter(Mandatory)] [ValidateSet("Users", "Computers", "Groups", "ForestInfo", "Sites", "Trusts", "Policies", "OrganizationalUnits", "DomainInfo", "DomainControllers", "CustomShares")] [string]$ObjectType, [Parameter()] [string]$Filter = "*", # Default filter [Parameter()] [string[]]$Properties, # Properties to retrieve [Parameter()] [array]$InputData, # Optional input data to process instead of retrieving via cmdlet [Parameter(Mandatory)] [scriptblock]$ProcessingScript, # Transformation logic for each object [string]$ActivityName = "Retrieving $ObjectType" ) # Define the capabilities for each ObjectType $objectTypeCapabilities = @{ "Users" = @{ Cmdlet = "Get-ADUser"; SupportsFilter = $true; SupportsProperties = $true; SupportsCredential = $true } "Computers" = @{ Cmdlet = "Get-ADComputer"; SupportsFilter = $true; SupportsProperties = $true; SupportsCredential = $true } "Groups" = @{ Cmdlet = "Get-ADGroup"; SupportsFilter = $true; SupportsProperties = $true; SupportsCredential = $true } "ForestInfo" = @{ Cmdlet = "Get-ADForest"; SupportsFilter = $false; SupportsProperties = $false; SupportsCredential = $true } "Sites" = @{ Cmdlet = "Get-ADReplicationSite"; SupportsFilter = $true; SupportsProperties = $true; SupportsCredential = $true } "Trusts" = @{ Cmdlet = "Get-ADTrust"; SupportsFilter = $true; SupportsProperties = $false; SupportsCredential = $true } "Policies" = @{ Cmdlet = "Get-GPO"; SupportsFilter = $false; SupportsProperties = $false; SupportsCredential = $false } "OrganizationalUnits" = @{ Cmdlet = "Get-ADOrganizationalUnit"; SupportsFilter = $true; SupportsProperties = $true; SupportsCredential = $true } "DomainInfo" = @{ Cmdlet = "Get-ADDomain"; SupportsFilter = $false; SupportsProperties = $false; SupportsCredential = $true } "DomainControllers" = @{ Cmdlet = "Get-ADDomainController"; SupportsFilter = $true; SupportsProperties = $false; SupportsCredential = $true } "CustomShares" = @{ Cmdlet = $null; SupportsFilter = $false; SupportsProperties = $false; SupportsCredential = $false } } # Validate ObjectType and retrieve capabilities if (-not $objectTypeCapabilities.ContainsKey($ObjectType)) { Write-Log "Unsupported ObjectType: $ObjectType" -Level Error throw "Unsupported ObjectType: $ObjectType" } $cmdletInfo = $objectTypeCapabilities[$ObjectType] $cmdletName = $cmdletInfo.Cmdlet $supportsFilter = $cmdletInfo.SupportsFilter $supportsProperties = $cmdletInfo.SupportsProperties $supportsCredential = $cmdletInfo.SupportsCredential # Ensure that centralized credentials are set, unless ObjectType does not support credentials if ($supportsCredential -and -not $script:adminCreds) { Write-Log "Admin credentials not found. Please run Get-DomainReport first." -Level Error return $null } elseif ($supportsCredential) { $Credential = $script:adminCreds } try { Write-Log "Starting retrieval of $ObjectType..." -Level Info if ($InputData) { # Processing pre-fetched data $total = $InputData.Count if ($total -eq 0) { Write-Log "No $ObjectType provided in InputData." -Level Warning return @() } } else { if ($cmdletName) { # Prepare count parameters $countParams = @{ } if ($supportsCredential) { $countParams['Credential'] = $Credential } if ($supportsFilter) { $countParams['Filter'] = $Filter } # Handle single-object cmdlets like Get-ADForest, Get-GPO, Get-ADDomain if ($ObjectType -in @("ForestInfo", "Policies", "DomainInfo")) { $total = 1 } else { # Attempt to retrieve objects to count them try { $total = (& $cmdletName @countParams | Measure-Object).Count } catch { Write-Log "Error counting objects for ${ObjectType}: $($_.Exception.Message)" -Level Error return $null } } if ($total -eq 0) { Write-Log "No $ObjectType found based on the specified criteria." -Level Warning return @() } } else { # For ObjectTypes like "CustomShares" which don't have a corresponding cmdlet $total = 0 Write-Log "No cmdlet associated with ObjectType $ObjectType. Proceeding with InputData only." -Level Info } } Write-Log "Retrieving and processing $total $ObjectType..." -Level Info if ($InputData) { $objects = $InputData } elseif ($cmdletName) { # Build retrieval parameters $getParams = @{ } if ($supportsCredential) { $getParams['Credential'] = $Credential } if ($supportsFilter) { $getParams['Filter'] = $Filter } if ($supportsProperties -and $Properties) { $getParams['Properties'] = $Properties } $objects = try { & $cmdletName @getParams } catch { Write-Log "Error retrieving ${ObjectType}: $($_.Exception.Message)" -Level Error return $null } } else { Write-Log "No data to process for ObjectType: $ObjectType" -Level Warning return @() } $count = 0 $results = @() foreach ($item in $objects) { $count++ try { # Apply the transformation logic provided by the caller $obj = & $ProcessingScript $item # Update progress using Show-ProgressHelper if ($total -gt 0) { $percent = [int]( ($count / $total) * 100 ) Show-ProgressHelper -Activity $ActivityName -Status "Processing $ObjectType $count of $total" -PercentComplete $percent } # Collect the transformed object $results += $obj } catch { Write-Log "Error processing ${ObjectType}: $($_.Exception.Message)" -Level Warning # Create a fallback object in case of processing error switch ($ObjectType) { "Users" { $errorObject = [PSCustomObject]@{ SamAccountName = $item.SamAccountName DisplayName = $null EmailAddress = $null Enabled = $null LastLogonDate = $null PasswordLastSet = $null PasswordNeverExpires = $null PasswordExpired = $null DistinguishedName = $item.DistinguishedName MemberOf = @() AccountStatus = "Error" AccessStatus = "Access Error: $($_.Exception.Message)" } Add-Member -InputObject $errorObject -MemberType ScriptMethod -Name "ToString" -Value { "SamAccountName=$($this.SamAccountName); Status=Error; Groups=0" } -Force $results += $errorObject } "Computers" { $errorObject = [PSCustomObject]@{ Name = $item.Name IPv4Address = $null DNSHostName = $null OperatingSystem = $null OperatingSystemVersion = $null Enabled = $null LastLogonDate = $null Created = $null Modified = $null DistinguishedName = $item.DistinguishedName ServicePrincipalNames = $null MemberOf = @() AccessStatus = "Access Error: $($_.Exception.Message)" NetworkStatus = "Error" IsAlive = $false } Add-Member -InputObject $errorObject -MemberType ScriptMethod -Name "ToString" -Value { "Name=$($this.Name); NetworkStatus=Error; IsAlive=$($this.IsAlive); Groups=0" } -Force $results += $errorObject } "Groups" { $errorObject = [PSCustomObject]@{ Name = $item.Name Description = $item.Description GroupCategory = $item.GroupCategory GroupScope = $item.GroupScope TotalNestedMemberCount = 0 Members = @() Created = $item.Created Modified = $item.Modified DistinguishedName = $item.DistinguishedName AccessStatus = "Access Error: $($_.Exception.Message)" } Add-Member -InputObject $errorObject -MemberType ScriptMethod -Name "ToString" -Value { "Name=$($this.Name); Status=Error" } -Force $results += $errorObject } "ForestInfo" { Write-Log "Error retrieving Forest Info: $($_.Exception.Message)" -Level Warning $results += $null } "Sites" { Write-Log "Error retrieving Site Info: $($_.Exception.Message)" -Level Warning $results += $null } "Trusts" { Write-Log "Error retrieving Trust Info: $($_.Exception.Message)" -Level Warning $results += $null } "Policies" { Write-Log "Error retrieving GPOs: $($_.Exception.Message)" -Level Warning $results += $null } "OrganizationalUnits" { Write-Log "Error retrieving Organizational Units: $($_.Exception.Message)" -Level Warning $results += $null } "DomainInfo" { Write-Log "Error retrieving Domain Info: $($_.Exception.Message)" -Level Warning $results += $null } "DomainControllers" { Write-Log "Error retrieving Domain Controllers: $($_.Exception.Message)" -Level Warning $results += $null } "CustomShares" { Write-Log "Error processing Share: $($_.Exception.Message)" -Level Warning $results += $null } default { Write-Log "Unhandled ObjectType: $ObjectType" -Level Warning $results += $null } } } } # Finalize progress using Show-ProgressHelper Show-ProgressHelper -Activity $ActivityName -Completed Write-Log "Successfully retrieved $($results.Count) $ObjectType." -Level Info return $results } catch { Write-Log "Failed to retrieve ${ObjectType}: $($_.Exception.Message)" -Level Error } } |