Private/Console.ps1

# Console output uses host/progress streams only; it never enters returned datasets.
function Get-PSIConsoleValue($Object,[string]$Name){if($null -ne $Object -and $null -ne $Object.PSObject.Properties[$Name]){return $Object.$Name};return $null}
function Get-PSIInventoryDisplayState {Get-Variable -Name PSIConsole -ValueOnly -ErrorAction SilentlyContinue}
function Test-PSIInventoryQuiet {$state=Get-PSIInventoryDisplayState;return ($null -ne $state -and $state.Quiet)}
function Start-PSIInventoryDisplay([string]$Inventory,[string]$Domain,[string]$OutputPath,[bool]$Sample,[bool]$Quiet){
 $Inventory=switch($Inventory){'ADInfrastructureInventory'{'AD Infrastructure Inventory'}'ADSitesAndServicesInventory'{'AD Sites and Services Inventory'}'ADForestInventory'{'AD Forest and Domain Inventory'}'ADTrustInventory'{'AD Trust Inventory'}'ADDnsInventory'{'AD DNS Configuration Inventory'}'ADGroupPolicyInventory'{'AD Group Policy Inventory'}'ADOrganizationalUnitInventory'{'AD Organizational Unit Inventory'}'ADComputerInventory'{'AD Computer Inventory'}'ADGroupInventory'{'AD Group Inventory'}'ADUserInventory'{'AD User Inventory'}default{$Inventory}}
 $script:PSIConsole=[pscustomobject]@{Inventory=$Inventory;Quiet=$Quiet;Clock=[diagnostics.stopwatch]::StartNew();Seen=@{};Names=@{};Completed=0;Total=-1;Failures=0;Records=0;Target='';LastPaint=-1.0;LastLine=-20.0;Stage='Starting';Sample=$Sample}
 if($Quiet){return}
 try{
  $version=(Import-PowerShellDataFile (Join-Path $script:PSIInventoryModuleRoot 'PSInsightInventory.psd1')).ModuleVersion
  Write-Host '';Write-Host ('-'*68) -ForegroundColor DarkGray
  Write-Host ('PSInsightInventory | v'+$version) -ForegroundColor Cyan
  Write-Host 'Active Directory Inventory';Write-Host 'Author: Jonathan Preetham';Write-Host 'License: MIT'
  Write-Host ('-'*68) -ForegroundColor DarkGray
  Write-Host ('Inventory : '+$Inventory);Write-Host ('Domain : '+$(if($Sample){'Fictional sample (no infrastructure access)'}else{$Domain}))
  Write-Host ('Output : '+$OutputPath);Write-Host ('Mode : '+$(if($Sample){'SAMPLE'}else{'LIVE - read only'}));Write-Host ''
 }catch{}
 Update-PSIInventoryDisplay -Stage 'Starting collection' -Force
}
function Update-PSIInventoryDisplay([string]$Stage='', [int]$Total=-1,[string]$Target='', [switch]$Force){
 $state=Get-PSIInventoryDisplayState;if($null -eq $state -or $state.Quiet){return}
 $d=$state;if($Stage){$d.Stage=$Stage};if($Total -ge 0){$d.Total=$Total};if($Target){$d.Target=$Target}
 $seconds=$d.Clock.Elapsed.TotalSeconds;if(-not $Force -and ($seconds-$d.LastPaint) -lt 0.4){return};$d.LastPaint=$seconds
 $elapsed=$d.Clock.Elapsed.ToString('hh\:mm\:ss');$spinner=@('|','/','-','\')[[int]($seconds*2)%4]
 $status=$spinner+' '+$d.Stage+' | elapsed '+$elapsed
 if($d.Total -gt 0){$status+=' | '+$d.Completed+'/'+$d.Total+' query outcomes'}else{$status+=' | working (total not known yet)'}
 $detail='Rows observed: '+$d.Records+' | Incomplete outcomes: '+$d.Failures
 if($d.Target){$detail+=' | Target / latest outcome: '+$d.Target}
 try{
  $percent=if($d.Total -gt 0){[int][math]::Min(100,[math]::Floor(100*$d.Completed/$d.Total))}else{-1}
  Write-Progress -Id 8511 -Activity ('PSInsightInventory - '+$d.Inventory) -Status $status -CurrentOperation $detail -PercentComplete $percent
  # Periodic plain text remains useful in hosts that hide native progress.
  if($Force -or ($seconds-$d.LastLine) -ge 15){Write-Host ('['+$elapsed+'] '+$d.Stage+' | '+$d.Completed+' outcomes | '+$d.Records+' rows | '+$d.Failures+' incomplete outcomes') -ForegroundColor DarkCyan;$d.LastLine=$seconds}
 }catch{}
}
function Receive-PSIInventoryDisplay([object[]]$Items,[int]$Total=-1){
 $state=Get-PSIInventoryDisplayState;if($null -eq $state -or $state.Quiet){return}
 $d=$state;if($Total -ge 0){$d.Total=$Total}
 foreach($item in $Items){
  $kind=[string](Get-PSIConsoleValue $item 'Kind');$key=[string](Get-PSIConsoleValue $item 'Key');$status=[string](Get-PSIConsoleValue $item 'Status')
  if($kind -eq 'Progress'){$d.Stage=[string](Get-PSIConsoleValue $item 'Stage');$d.Target=[string](Get-PSIConsoleValue $item 'Target');continue}
  if($kind -eq 'Context'){$target=[string](Get-PSIConsoleValue $item 'Server');if($target){$d.Target=$target};continue}
  if(-not $key -or -not $status){continue}
  $target=[string](Get-PSIConsoleValue $item 'Target');$identity=$target+'|'+$key
  if($d.Seen.ContainsKey($identity)){continue};$d.Seen[$identity]=$true;$d.Completed++
  if($status -in @('Failed','TimedOut','Partial','NotAttempted')){$d.Failures++}
  $records=@((Get-PSIConsoleValue $item 'Records')|Where-Object{$null -ne $_});$d.Records+=$records.Count
  if($key -eq 'groups'){$d.Total=1+$records.Count;foreach($r in $records){$id=[string](Get-PSIConsoleValue $r 'Id');if($id){$d.Names[$id]=[string](Get-PSIConsoleValue $r 'Name')}}}
  if($key -like 'members:*'){$id=$key.Substring(8);$d.Target=if($d.Names.ContainsKey($id)){$d.Names[$id]}else{$key}}
  elseif($target){$d.Target=$target}else{$d.Target=$key}
 }
 if($d.Stage -eq 'Starting collection'){$d.Stage='Collecting configuration'}
 Update-PSIInventoryDisplay
}
function Complete-PSIInventoryCollectionDisplay([object[]]$Collection){
 $state=Get-PSIInventoryDisplayState;if($null -eq $state -or $state.Quiet){return}
 $state.Completed=@($Collection).Count;$state.Total=@($Collection).Count
 $state.Failures=@($Collection|Where-Object{[string](Get-PSIConsoleValue $_ 'Status') -notin @('Succeeded','NotApplicable')}).Count
}
function Stop-PSIInventoryDisplay($Result,[switch]$Failed){
 $state=Get-PSIInventoryDisplayState;if($null -eq $state){return};$d=$state
 try{
  if(-not $d.Quiet){
   Write-Progress -Id 8511 -Activity 'PSInsightInventory' -Completed
   Write-Host '';Write-Host $(if($Failed){'COLLECTION STOPPED'}else{'REPORT SAVED'}) -ForegroundColor $(if($Failed){'Yellow'}else{'Cyan'})
   Write-Host ('Elapsed: '+$d.Clock.Elapsed.ToString('hh\:mm\:ss'))
   if(-not $Failed){
    Write-Host ('Query outcomes observed: '+$d.Completed+' | Incomplete outcomes: '+$d.Failures) -ForegroundColor $(if($d.Failures){'Yellow'}else{'Gray'})
    if($d.Sample){Write-Host 'Sample data only - no infrastructure was contacted.' -ForegroundColor Yellow}
    $path=Get-PSIConsoleValue $Result 'HtmlReport';if($path){Write-Host ('Report: '+$path)}
   }else{Write-Host 'Review the error and run log for details.' -ForegroundColor Yellow}
   Write-Host ('-'*68) -ForegroundColor DarkGray
  }
 }catch{}finally{$script:PSIConsole=$null}
}
$script:PSIConsole=$null