Src/Private/Report/Get-AbrVbrBackupServerInfo.ps1


function Get-AbrVbrBackupServerInfo {
    <#
    .SYNOPSIS
    Used by As Built Report to retrieve Veeam VBR Backup Server Information
    .DESCRIPTION
        Documents the configuration of Veeam VBR in Word/HTML/Text formats using PScribo.
    .NOTES
        Version: 1.0.0
        Author: Jonathan Colon
        Twitter: @jcolonfzenpr
        Github: rebelinux
        Credits: Iain Brighton (@iainbrighton) - PScribo module
 
    .LINK
        https://github.com/AsBuiltReport/AsBuiltReport.Veeam.VBR
    #>

    [CmdletBinding()]
    param (

    )

    begin {
        Write-PScriboMessage "Discovering Veeam VB&R Server information from $System."
        $LocalizedData = $reportTranslate.GetAbrVbrBackupServerInfo
        Show-AbrDebugExecutionTime -Start -TitleMessage 'Backup Server'
    }

    process {
        try {
            $script:BackupServers = switch ($VbrVersion) {
                { $_ -lt 13 } { Get-VBRServer -Type Local }
                default { Get-VBRServer | Where-Object { $_.Description -eq 'Backup server' } }
            }
            if (($VbrVersion -gt 13) -and (Get-VBRServer | Where-Object { $_.Description -eq 'Backup server' -and $_.Type -eq 'Linux' } )) {
                $VeeamVersion = @{
                    DisplayVersion = $VbrVersion
                }
                $VeeamDBFlavor = @{
                    SqlActiveConfiguration = 'PostgreSql'
                }

                $VeeamDBInfo = @{
                    SqlDatabaseName = 'VeeamBackup'
                    SqlHostName = 'localhost'
                    SqlHostPort = '5432'
                }

                $VeeamInfo = @{
                    BackupServerPort = '443'
                    SecureConnectionsPort = '443'
                    CloudServerPort = '10003'
                    CloudSvcPort = '6169'
                    CorePath = '/opt/veeam'
                }
            }
            if ($BackupServers) {
                Section -Style Heading3 $LocalizedData.Heading {
                    Paragraph $LocalizedData.Paragraph
                    BlankLine
                    $OutObj = @()
                    try {
                        foreach ($BackupServer in $BackupServers) {
                            if (-not ($BackupServer.Type -eq 'Linux' -and $BackupServer.Description -eq 'Backup server')) {
                                if ($ClientOSVersion -eq 'Win32NT') {
                                    $CimSession = try { New-CimSession $BackupServer.Name -Credential $Credential -Authentication $Options.PSDefaultAuthentication -Name 'CIMBackupServer' -ErrorAction Stop } catch { Write-PScriboMessage -IsWarning "Backup Server Section: New-CimSession: Unable to connect to $($BackupServer.Name): $($_.Exception.MessageId)" }
                                }

                                if ($ClientOSVersion -eq 'Win32NT') {
                                    $PssSession = try { New-PSSession $BackupServer.Name -Credential $Credential -Authentication $Options.PSDefaultAuthentication -ErrorAction Stop -Name 'PSSBackupServer' } catch {
                                        if (-not $_.Exception.MessageId) {
                                            $ErrorMessage = $_.FullyQualifiedErrorId
                                        } else { $ErrorMessage = $_.Exception.MessageId }
                                        Write-PScriboMessage -IsWarning "Backup Server Section: New-PSSession: Unable to connect to $($BackupServer.Name): $ErrorMessage"
                                    }
                                }
                            }
                            $SecurityOptions = Get-VBRSecurityOptions
                            if ($CimSession) {
                                try { $DomainJoined = Get-CimInstance -Class Win32_ComputerSystem -Property PartOfDomain -CimSession $CimSession } catch { 'Unknown' }
                            }
                            Write-PScriboMessage ($LocalizedData.Collecting -f $BackupServer.Name)

                            if (-not ($BackupServer.Type -eq 'Linux' -and $BackupServer.Description -eq 'Backup server')) {
                                if ($PssSession) {
                                    try {
                                        $script:VeeamVersion = Invoke-Command -Session $PssSession -ErrorAction SilentlyContinue -ScriptBlock { Get-ChildItem -Recurse HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall | Get-ItemProperty | Where-Object { $_.DisplayName -match 'Veeam Backup & Replication Server' } | Select-Object -Property DisplayVersion }
                                    } catch { Write-PScriboMessage -IsWarning "Backup Server Invoke-Command Section: $($_.Exception.Message)" }
                                    try {
                                        $VeeamInfo = Invoke-Command -Session $PssSession -ErrorAction SilentlyContinue -ScriptBlock { Get-ItemProperty -Path 'HKLM:\SOFTWARE\Veeam\Veeam Backup and Replication' }
                                    } catch { Write-PScriboMessage -IsWarning "Backup Server Invoke-Command Section: $($_.Exception.Message)" }
                                    try {
                                        $VeeamDBFlavor = Invoke-Command -Session $PssSession -ErrorAction SilentlyContinue -ScriptBlock { Get-ItemProperty -Path 'HKLM:\SOFTWARE\Veeam\Veeam Backup and Replication\DatabaseConfigurations' }
                                    } catch { Write-PScriboMessage -IsWarning "Backup Server Invoke-Command Section: $($_.Exception.Message)" }
                                    try {
                                        $VeeamDBInfo = Invoke-Command -Session $PssSession -ErrorAction SilentlyContinue -ScriptBlock { Get-ItemProperty -Path "HKLM:\SOFTWARE\Veeam\Veeam Backup and Replication\DatabaseConfigurations\$(($Using:VeeamDBFlavor).SqlActiveConfiguration)" }
                                    } catch { Write-PScriboMessage -IsWarning "Backup Server Invoke-Command Section: $($_.Exception.Message)" }
                                } else {
                                    Write-PScriboMessage -IsWarning "Backup Server Section: Unable to get Backup Server information: WinRM disabled or not configured on $($BackupServer.Name)."
                                }
                            }


                            $inObj = [ordered] @{
                                $LocalizedData.ServerName = $BackupServer.Name
                                $LocalizedData.IsDomainJoined = $DomainJoined.PartOfDomain
                                $LocalizedData.Version = switch (($VeeamVersion).count) {
                                    0 { '--' }
                                    default { $VeeamVersion.DisplayVersion }
                                }
                                $LocalizedData.DatabaseType = switch ([string]::IsNullOrEmpty($VeeamDBFlavor.SqlActiveConfiguration)) {
                                    $true { '--' }
                                    $false { $VeeamDBFlavor.SqlActiveConfiguration }
                                    default { 'Unknown' }
                                }
                                $LocalizedData.DatabaseName = switch ([string]::IsNullOrEmpty($VeeamDBInfo.SqlDatabaseName)) {
                                    $true { '--' }
                                    $false { $VeeamDBInfo.SqlDatabaseName }
                                    default { 'Unknown' }
                                }
                                $LocalizedData.DatabaseServer = switch ([string]::IsNullOrEmpty($VeeamDBInfo.SqlHostName)) {
                                    $true { '--' }
                                    $false { $VeeamDBInfo.SqlHostName }
                                    default { 'Unknown' }
                                }
                                $LocalizedData.DatabasePort = switch ([string]::IsNullOrEmpty($VeeamDBInfo.SqlHostPort)) {
                                    $true { '--' }
                                    $false { "$($VeeamDBInfo.SqlHostPort)/TCP" }
                                    default { 'Unknown' }
                                }
                                $LocalizedData.ConnectionPorts = switch (($VeeamInfo.BackupServerPort).count) {
                                    0 { '--' }
                                    default { "Backup Server Port: $($VeeamInfo.BackupServerPort)`r`nSecure Connections Port: $($VeeamInfo.SecureConnectionsPort)`r`nCloud Server Port: $($VeeamInfo.CloudServerPort)`r`nCloud Service Port: $($VeeamInfo.CloudSvcPort)" }
                                }
                                $LocalizedData.InstallPath = switch (($VeeamInfo.CorePath).count) {
                                    0 { '--' }
                                    default { $VeeamInfo.CorePath }
                                }
                                $LocalizedData.AuditLogsPath = $SecurityOptions.AuditLogsPath
                                $LocalizedData.CompressOldAuditLogs = $SecurityOptions.CompressOldAuditLogs
                                $LocalizedData.FipsCompliantMode = switch ($SecurityOptions.FipsCompliantModeEnabled) {
                                    'True' { 'Enabled' }
                                    'False' { 'Disabled' }
                                }
                                $LocalizedData.LinuxHostAuthentication = switch ($SecurityOptions.HostPolicy.Type) {
                                    'All' { 'Add all discovered host to the list automatically' }
                                    'KnownHosts' { 'Add unknown host to the list manually' }
                                }
                                $LocalizedData.LoggingLevel = $VeeamInfo.LoggingLevel

                            }

                            if ($Null -notlike $VeeamInfo.LogDirectory) {
                                $inObj.add($LocalizedData.LogDirectory, ($VeeamInfo.LogDirectory))
                            }

                            $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
                        }
                    } catch {
                        Write-PScriboMessage -IsWarning "Backup Server Section: $($_.Exception.Message)"
                    }

                    if ($HealthCheck.Infrastructure.BackupServer) {
                        $OutObj | Where-Object { $_."$($LocalizedData.LoggingLevel)" -gt 4 } | Set-Style -Style Warning -Property $LocalizedData.LoggingLevel
                        $OutObj | Where-Object { $_."$($LocalizedData.IsDomainJoined)" -eq 'Yes' } | Set-Style -Style Warning -Property $LocalizedData.IsDomainJoined
                    }

                    $TableParams = @{
                        Name = "$($LocalizedData.TableHeading) - $($BackupServer.Name.Split('.')[0])"
                        List = $true
                        ColumnWidths = 40, 60
                    }
                    if ($Report.ShowTableCaptions) {
                        $TableParams['Caption'] = "- $($TableParams.Name)"
                    }
                    $OutObj | Table @TableParams
                    if ($HealthCheck.Infrastructure.BestPractice) {
                        if ($OutObj | Where-Object { $_."$($LocalizedData.IsDomainJoined)" -eq 'Yes' }) {
                            Paragraph $LocalizedData.healthCheck -Bold -Underline
                            BlankLine
                            Paragraph {
                                Text $LocalizedData.bestPractice -Bold
                                Text $LocalizedData.domainJoinBestPracticeText
                            }
                            BlankLine
                            Paragraph {
                                Text $LocalizedData.Reference -Bold
                                Text $LocalizedData.domainJoinReference
                            }
                            BlankLine
                        }
                    }
                    #---------------------------------------------------------------------------------------------#
                    # Backup Server Inventory & Software Summary Section #
                    #---------------------------------------------------------------------------------------------#
                    try {
                        Write-PScriboMessage "Hardware Inventory Status set as $($Options.EnableHardwareInventory)."
                        if ($Options.EnableHardwareInventory -and ($PssSession)) {
                            Write-PScriboMessage ($LocalizedData.CollectingInventory -f $BackupServer.Name)
                            if ($CimSession) {
                                $License = Get-CimInstance -Query 'Select * from SoftwareLicensingProduct' -CimSession $CimSession | Where-Object { $_.LicenseStatus -eq 1 }
                                $HWCPU = Get-CimInstance -Class Win32_Processor -CimSession $CimSession
                                $HWBIOS = Get-CimInstance -Class Win32_Bios -CimSession $CimSession
                            }

                            if ($HW = Invoke-Command -Session $PssSession -ScriptBlock { Get-ComputerInfo }) {
                                Section -Style Heading4 $LocalizedData.HWInventoryHeading {
                                    $OutObj = @()
                                    $inObj = [ordered] @{
                                        $LocalizedData.Name = $HW.CsDNSHostName
                                        $LocalizedData.WindowsProductName = $HW.WindowsProductName
                                        $LocalizedData.WindowsCurrentVersion = $HW.WindowsCurrentVersion
                                        $LocalizedData.WindowsBuildNumber = $HW.OsVersion
                                        $LocalizedData.WindowsInstallType = $HW.WindowsInstallationType
                                        $LocalizedData.ADDomain = $HW.CsDomain
                                        $LocalizedData.WindowsInstallDate = $HW.OsInstallDate
                                        $LocalizedData.TimeZone = $HW.TimeZone
                                        $LocalizedData.LicenseType = $License.ProductKeyChannel
                                        $LocalizedData.PartialProductKey = $License.PartialProductKey
                                        $LocalizedData.Manufacturer = $HW.CsManufacturer
                                        $LocalizedData.Model = $HW.CsModel
                                        $LocalizedData.SerialNumber = $HWBIOS.SerialNumber
                                        $LocalizedData.BiosType = $HW.BiosFirmwareType
                                        $LocalizedData.BIOSVersion = $HWBIOS.Version
                                        $LocalizedData.ProcessorManufacturer = $HWCPU[0].Manufacturer
                                        $LocalizedData.ProcessorModel = $HWCPU[0].Name
                                        $LocalizedData.CPUCores = ($HWCPU.NumberOfCores | Measure-Object -Sum).Sum
                                        $LocalizedData.LogicalCores = ($HWCPU.NumberOfLogicalProcessors | Measure-Object -Sum).Sum
                                        $LocalizedData.PhysicalMemory = ConvertTo-FileSizeString -RoundUnits $Options.RoundUnits -Size $HW.CsTotalPhysicalMemory
                                    }
                                    $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)

                                    if ($HealthCheck.Infrastructure.Server) {
                                        $OutObj | Where-Object { $_."$($LocalizedData.CPUCores)" -lt 2 } | Set-Style -Style Warning -Property $LocalizedData.CPUCores
                                        if ([int]([regex]::Matches($OutObj."$($LocalizedData.PhysicalMemory)", '\d+(?!.*\d+)').value) -lt 8) { $OutObj | Set-Style -Style Warning -Property $LocalizedData.PhysicalMemory }
                                    }

                                    $TableParams = @{
                                        Name = "$($LocalizedData.HWInventoryHeading) - $($BackupServer.Name.Split('.')[0])"
                                        List = $true
                                        ColumnWidths = 40, 60
                                    }
                                    if ($Report.ShowTableCaptions) {
                                        $TableParams['Caption'] = "- $($TableParams.Name)"
                                    }
                                    $OutObj | Table @TableParams
                                    if ($HealthCheck.Infrastructure.BestPractice) {
                                        if (([int]([regex]::Matches($OutObj."$($LocalizedData.PhysicalMemory)", '\d+(?!.*\d+)').value) -lt 8) -or ($OutObj | Where-Object { $_."$($LocalizedData.CPUCores)" -lt 2 })) {
                                            Paragraph $LocalizedData.healthCheck -Bold -Underline
                                            BlankLine
                                            Paragraph {
                                                Text $LocalizedData.bestPractice -Bold
                                                Text $LocalizedData.minConfigBestPracticeText
                                            }
                                            BlankLine
                                        }
                                    }
                                    #---------------------------------------------------------------------------------------------#
                                    # Backup Server Local Disk Inventory Section #
                                    #---------------------------------------------------------------------------------------------#
                                    if ($InfoLevel.Infrastructure.BackupServer -ge 3) {
                                        try {
                                            $HostDisks = Invoke-Command -Session $PssSession -ScriptBlock { Get-Disk | Where-Object { $_.BusType -ne 'iSCSI' -and $_.BusType -ne 'Fibre Channel' } }
                                            if ($HostDisks) {
                                                Section -Style NOTOCHeading5 -ExcludeFromTOC $LocalizedData.LocalDisksHeading {
                                                    $LocalDiskReport = @()
                                                    foreach ($Disk in $HostDisks) {
                                                        try {
                                                            $TempLocalDiskReport = [PSCustomObject]@{
                                                                $LocalizedData.DiskNumber = $Disk.Number
                                                                $LocalizedData.Model = $Disk.Model
                                                                $LocalizedData.SerialNumber = $Disk.SerialNumber
                                                                $LocalizedData.PartitionStyle = $Disk.PartitionStyle
                                                                $LocalizedData.DiskSize = ConvertTo-FileSizeString -RoundUnits $Options.RoundUnits -Size $Disk.Size
                                                            }
                                                            $LocalDiskReport += $TempLocalDiskReport
                                                        } catch {
                                                            Write-PScriboMessage -IsWarning "Backup Server Local Disk $($Disk.Number) Section: $($_.Exception.Message)"
                                                        }
                                                    }
                                                    $TableParams = @{
                                                        Name = "$($LocalizedData.TableHeading) - $($LocalizedData.LocalDisksHeading)"
                                                        List = $false
                                                        ColumnWidths = 20, 20, 20, 20, 20
                                                    }
                                                    if ($Report.ShowTableCaptions) {
                                                        $TableParams['Caption'] = "- $($TableParams.Name)"
                                                    }
                                                    $LocalDiskReport | Sort-Object -Property $LocalizedData.DiskNumber | Table @TableParams
                                                }
                                            }
                                        } catch {
                                            Write-PScriboMessage -IsWarning "Backup Server Local Disk Section: $($_.Exception.Message)"
                                        }
                                        #---------------------------------------------------------------------------------------------#
                                        # Backup Server SAN Disk Inventory Section #
                                        #---------------------------------------------------------------------------------------------#
                                        try {
                                            $SanDisks = Invoke-Command -Session $PssSession -ScriptBlock { Get-Disk | Where-Object { $_.BusType -eq 'iSCSI' -or $_.BusType -eq 'Fibre Channel' } }
                                            if ($SanDisks) {
                                                Section -Style NOTOCHeading5 -ExcludeFromTOC $LocalizedData.SANDisksHeading {
                                                    $SanDiskReport = @()
                                                    foreach ($Disk in $SanDisks) {
                                                        try {
                                                            $TempSanDiskReport = [PSCustomObject]@{
                                                                $LocalizedData.DiskNumber = $Disk.Number
                                                                $LocalizedData.Model = $Disk.Model
                                                                $LocalizedData.SerialNumber = $Disk.SerialNumber
                                                                $LocalizedData.PartitionStyle = $Disk.PartitionStyle
                                                                $LocalizedData.DiskSize = ConvertTo-FileSizeString -RoundUnits $Options.RoundUnits -Size $Disk.Size
                                                            }
                                                            $SanDiskReport += $TempSanDiskReport
                                                        } catch {
                                                            Write-PScriboMessage -IsWarning "Backup Server SAN Disk $($Disk.Number) Section: $($_.Exception.Message)"
                                                        }
                                                    }
                                                    $TableParams = @{
                                                        Name = "$($LocalizedData.TableHeading) - $($LocalizedData.SANDisksHeading)"
                                                        List = $false
                                                        ColumnWidths = 20, 20, 20, 20, 20
                                                    }
                                                    if ($Report.ShowTableCaptions) {
                                                        $TableParams['Caption'] = "- $($TableParams.Name)"
                                                    }
                                                    $SanDiskReport | Sort-Object -Property $LocalizedData.DiskNumber | Table @TableParams
                                                }
                                            }
                                        } catch {
                                            Write-PScriboMessage -IsWarning "Backup Server SAN Disk Section: $($_.Exception.Message)"
                                        }
                                    }
                                    #---------------------------------------------------------------------------------------------#
                                    # Backup Server Volume Inventory Section #
                                    #---------------------------------------------------------------------------------------------#
                                    try {
                                        $HostVolumes = Invoke-Command -Session $PssSession -ScriptBlock { Get-Volume | Where-Object { $_.DriveType -ne 'CD-ROM' -and $NUll -ne $_.DriveLetter } }
                                        if ($HostVolumes) {
                                            Section -Style NOTOCHeading5 -ExcludeFromTOC $LocalizedData.HostVolumesHeading {
                                                $HostVolumeReport = @()
                                                foreach ($HostVolume in $HostVolumes) {
                                                    try {
                                                        $TempHostVolumeReport = [PSCustomObject]@{
                                                            $LocalizedData.DriveLetter = $HostVolume.DriveLetter
                                                            $LocalizedData.FileSystemLabel = $HostVolume.FileSystemLabel
                                                            $LocalizedData.FileSystem = $HostVolume.FileSystem
                                                            $LocalizedData.Size = ConvertTo-FileSizeString -RoundUnits $Options.RoundUnits -Size $HostVolume.Size
                                                            $LocalizedData.FreeSpace = ConvertTo-FileSizeString -RoundUnits $Options.RoundUnits -Size $HostVolume.SizeRemaining
                                                            $LocalizedData.HealthStatus = $HostVolume.HealthStatus
                                                        }
                                                        $HostVolumeReport += $TempHostVolumeReport
                                                    } catch {
                                                        Write-PScriboMessage -IsWarning "Backup Server Host Volume $($HostVolume.DriveLetter) Section: $($_.Exception.Message)"
                                                    }
                                                }
                                                $TableParams = @{
                                                    Name = "$($LocalizedData.TableHeading) - $($LocalizedData.HostVolumesHeading)"
                                                    List = $false
                                                    ColumnWidths = 15, 15, 15, 20, 20, 15
                                                }
                                                if ($Report.ShowTableCaptions) {
                                                    $TableParams['Caption'] = "- $($TableParams.Name)"
                                                }
                                                $HostVolumeReport | Sort-Object -Property $LocalizedData.DriveLetter | Table @TableParams
                                            }
                                        }
                                    } catch {
                                        Write-PScriboMessage -IsWarning "Backup Server Host Volume Section: $($_.Exception.Message)"
                                    }
                                    #---------------------------------------------------------------------------------------------#
                                    # Backup Server Network Inventory Section #
                                    #---------------------------------------------------------------------------------------------#
                                    if ($InfoLevel.Infrastructure.BackupServer -ge 2) {
                                        try {
                                            $HostAdapters = Invoke-Command -Session $PssSession { Get-NetAdapter }
                                            if ($HostAdapters) {
                                                Section -Style NOTOCHeading5 -ExcludeFromTOC $LocalizedData.NetworkAdaptersHeading {
                                                    $HostAdaptersReport = @()
                                                    foreach ($HostAdapter in $HostAdapters) {
                                                        try {
                                                            $TempHostAdaptersReport = [PSCustomObject]@{
                                                                $LocalizedData.AdapterName = $HostAdapter.Name
                                                                $LocalizedData.AdapterDescription = $HostAdapter.InterfaceDescription
                                                                $LocalizedData.MacAddress = $HostAdapter.MacAddress
                                                                $LocalizedData.LinkSpeed = $HostAdapter.LinkSpeed
                                                            }
                                                            $HostAdaptersReport += $TempHostAdaptersReport
                                                        } catch {
                                                            Write-PScriboMessage -IsWarning "Backup Server Host Volume $($HostAdapter.Name) Section: $($_.Exception.Message)"
                                                        }
                                                    }
                                                    $TableParams = @{
                                                        Name = "$($LocalizedData.TableHeading) - $($LocalizedData.NetworkAdaptersHeading)"
                                                        List = $false
                                                        ColumnWidths = 30, 35, 20, 15
                                                    }
                                                    if ($Report.ShowTableCaptions) {
                                                        $TableParams['Caption'] = "- $($TableParams.Name)"
                                                    }
                                                    $HostAdaptersReport | Sort-Object -Property $LocalizedData.AdapterName | Table @TableParams
                                                }
                                            }
                                        } catch {
                                            Write-PScriboMessage -IsWarning "Backup Server Host Volume Section: $($_.Exception.Message)"
                                        }
                                        try {
                                            $NetIPs = Invoke-Command -Session $PssSession { Get-NetIPConfiguration | Where-Object -FilterScript { ($_.NetAdapter.Status -eq 'Up') } }
                                            if ($NetIPs) {
                                                Section -Style NOTOCHeading5 -ExcludeFromTOC $LocalizedData.IPAddressHeading {
                                                    $NetIpsReport = @()
                                                    foreach ($NetIp in $NetIps) {
                                                        try {
                                                            $TempNetIpsReport = [PSCustomObject]@{
                                                                $LocalizedData.InterfaceName = $NetIp.InterfaceAlias
                                                                $LocalizedData.InterfaceDescription = $NetIp.InterfaceDescription
                                                                $LocalizedData.IPv4Addresses = $NetIp.IPv4Address.IPAddress -join ','
                                                                $LocalizedData.SubnetMask = $NetIp.IPv4Address[0].PrefixLength
                                                                $LocalizedData.IPv4Gateway = $NetIp.IPv4DefaultGateway.NextHop
                                                            }
                                                            $NetIpsReport += $TempNetIpsReport
                                                        } catch {
                                                            Write-PScriboMessage -IsWarning "Backup Server Host Volume $($NetIp.InterfaceAlias) Section: $($_.Exception.Message)"
                                                        }
                                                    }
                                                    $TableParams = @{
                                                        Name = "$($LocalizedData.TableHeading) - $($LocalizedData.IPAddressHeading)"
                                                        List = $false
                                                        ColumnWidths = 25, 25, 20, 10, 20
                                                    }
                                                    if ($Report.ShowTableCaptions) {
                                                        $TableParams['Caption'] = "- $($TableParams.Name)"
                                                    }
                                                    $NetIpsReport | Sort-Object -Property $LocalizedData.InterfaceName | Table @TableParams
                                                }
                                            }
                                        } catch {
                                            Write-PScriboMessage -IsWarning "Backup Server Host Volume Section: $($_.Exception.Message)"
                                        }
                                    }
                                }
                            } else {
                                Write-PScriboMessage -IsWarning "Backup Server Section: Unable to get Backup Server Hardware information: WinRM disabled or not configured on $($BackupServer.Name)."
                            }
                        }
                    } catch {
                        Write-PScriboMessage -IsWarning "Backup Server Inventory Summary Section: $($_.Exception.Message)"
                    }
                    try {
                        Write-PScriboMessage "Infrastructure Backup Server InfoLevel set at $($InfoLevel.Infrastructure.BackupServer)."
                        if ($InfoLevel.Infrastructure.BackupServer -ge 3 -and $Options.EnableHardwareInventory -and ($PssSession)) {
                            if ($PssSession) {
                                $VeeamInfo = Invoke-Command -Session $PssSession -ErrorAction SilentlyContinue -ScriptBlock { Get-ItemProperty -Path 'HKLM:\SOFTWARE\Veeam\Veeam Backup and Replication' }
                                $DefaultRegistryHash = @{
                                    'AgentLogging' = '1'
                                    'AgentLogOptions' = 'flush'
                                    'LoggingLevel' = '4'
                                    'VNXBlockNaviSECCliPath' = 'C:\Program Files\Veeam\Backup and Replication\Backup\EMC Navisphere CLI\NaviSECCli.exe'
                                    'VNXeUemcliPath' = 'C:\Program Files\Veeam\Backup and Replication\Backup\EMC Unisphere CLI\3.0.1\uemcli.exe'
                                    'SqlLockInfo' = ''
                                    'CloudServerPort' = '10003'
                                    'SqlDatabaseName' = 'VeeamBackup'
                                    'SqlInstanceName' = 'VEEAMSQL2016'
                                    'SqlServerName' = ''
                                    'SqlLogin' = ''
                                    'CorePath' = 'C:\Program Files\Veeam\Backup and Replication\Backup\'
                                    'BackupServerPort' = '9392'
                                    'SecureConnectionsPort' = '9401'
                                    'VddkReadBufferSize' = '0'
                                    'EndPointServerPort' = '10001'
                                    'SqlSecuredPassword' = ''
                                    'IsComponentsUpdateRequired' = '0'
                                    'LicenseAutoUpdate' = '1'
                                    'CloudSvcPort' = '6169'
                                    'VBRServiceRestartNeeded' = '0'
                                    'ImportServers' = '0'
                                    'MaxLogCount' = '10'
                                    'MaxLogSize' = '10240'
                                    'RunspaceId' = '0000'
                                    'ProviderCredentialsId' = ''
                                    'ProviderInfo' = ''
                                    'ProviderId' = ''
                                    'EntraIdSqlHostName' = 'localhost'
                                    'EntraIdSqlHostPort' = '5432'
                                    'EntraIdSqlPassword' = ''
                                    'EntraIdSqlServiceName' = 'postgresql-x64-15'
                                    'EntraIdSqlUserName' = 'postgres'
                                    'HighestDetectedVMCVersion' = ''
                                }
                                if ($VeeamInfo) {
                                    $OutObj = @()
                                    $Hashtable = $VeeamInfo | ForEach-Object {
                                        foreach ($prop in $_.psobject.Properties.Where({ $_.Name -notlike 'PS*' })) {
                                            [pscustomobject] @{
                                                Key = $prop.Name
                                                Value = $prop.Value
                                            }
                                        }
                                    }
                                    foreach ($Registry in $Hashtable) {
                                        if ($Registry.Key -notin $DefaultRegistryHash.Keys) {
                                            $inObj = [ordered] @{
                                                $LocalizedData.RegistryKey = $Registry.Key
                                                $LocalizedData.RegistryValue = switch (($Registry.Value).count) {
                                                    0 { '--' }
                                                    1 { $Registry.Value }
                                                    default { $Registry.Value -join ', ' }
                                                }
                                            }
                                            $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
                                        }
                                    }

                                    $TableParams = @{
                                        Name = "$($LocalizedData.NonDefaultRegistryHeading) - $($BackupServer.Name.Split('.')[0])"
                                        List = $false
                                        ColumnWidths = 50, 50
                                    }
                                    if ($Report.ShowTableCaptions) {
                                        $TableParams['Caption'] = "- $($TableParams.Name)"
                                    }
                                }
                                if ($OutObj) {
                                    Section -Style Heading4 $LocalizedData.NonDefaultRegistryHeading {
                                        $OutObj | Sort-Object -Property $LocalizedData.RegistryKey | Table @TableParams
                                    }
                                }
                            }
                        }
                    } catch {
                        Write-PScriboMessage -IsWarning "Backup Server Non-Default Registry Keys Section: $($_.Exception.Message)"
                    }
                    #---------------------------------------------------------------------------------------------#
                    # Backup Server Services Information Section #
                    #---------------------------------------------------------------------------------------------#
                    if ($HealthCheck.Infrastructure.Server) {
                        if ($PssSession -and $Options.EnableHardwareInventory) {
                            try {
                                Write-PScriboMessage "Infrastructure Backup Server InfoLevel set at $($InfoLevel.Infrastructure.BackupServer)."
                                if ($InfoLevel.Infrastructure.BackupServer -ge 2) {
                                    Write-PScriboMessage ($LocalizedData.CollectingServices -f $BackupServer.Name)
                                    $Available = Invoke-Command -Session $PssSession -ScriptBlock { Get-Service 'W32Time' | Select-Object DisplayName, Name, Status }
                                    if ($Available) {
                                        $Services = Invoke-Command -Session $PssSession -ScriptBlock { Get-Service Veeam* }
                                        Section -Style Heading4 $LocalizedData.ServicesStatusHeading {
                                            $OutObj = @()
                                            foreach ($Service in $Services) {
                                                Write-PScriboMessage ($LocalizedData.CollectingServiceStatus -f $Service.DisplayName, $BackupServer.Name)
                                                $inObj = [ordered] @{
                                                    $LocalizedData.DisplayName = $Service.DisplayName
                                                    $LocalizedData.ShortName = $Service.Name
                                                    $LocalizedData.Status = $Service.Status
                                                }
                                                $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
                                            }

                                            if ($HealthCheck.Infrastructure.Server) {
                                                $OutObj | Where-Object { $_."$($LocalizedData.Status)" -notlike 'Running' } | Set-Style -Style Warning -Property $LocalizedData.Status
                                            }

                                            $TableParams = @{
                                                Name = "$($LocalizedData.ServicesStatusHeading) - $($BackupServer.Name.Split('.')[0])"
                                                List = $false
                                                ColumnWidths = 45, 35, 20
                                            }
                                            if ($Report.ShowTableCaptions) {
                                                $TableParams['Caption'] = "- $($TableParams.Name)"
                                            }
                                            $OutObj | Table @TableParams
                                        }
                                    }
                                }
                            } catch {
                                Write-PScriboMessage -IsWarning "Backup Server Service Status Section: $($_.Exception.Message)"
                            }
                        }
                    }
                    if ($HealthCheck.Infrastructure.BestPractice -and $PssSession) {
                        try {
                            $UpdObj = @()
                            $Updates = Invoke-Command -Session $PssSession -ScriptBlock { (New-Object -ComObject Microsoft.Update.Session).CreateupdateSearcher().Search('IsHidden=0 and IsInstalled=0').Updates | Select-Object Title, KBArticleIDs }
                            $UpdObj += if ($Updates) {
                                $OutObj = @()
                                foreach ($Update in $Updates) {
                                    try {
                                        $inObj = [ordered] @{
                                            $LocalizedData.KBArticle = "KB$($Update.KBArticleIDs)"
                                            $LocalizedData.Name = $Update.Title
                                        }
                                        $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)

                                        if ($HealthCheck.OperatingSystem.Updates) {
                                            $OutObj | Set-Style -Style Warning
                                        }
                                    } catch {
                                        Write-PScriboMessage -IsWarning $_.Exception.Message
                                    }
                                }

                                $OutObj | Set-Style -Style Warning

                                $TableParams = @{
                                    Name = "$($LocalizedData.MissingUpdatesHeading) - $($BackupServer.Name.Split('.')[0])"
                                    List = $false
                                    ColumnWidths = 40, 60
                                }
                                if ($Report.ShowTableCaptions) {
                                    $TableParams['Caption'] = "- $($TableParams.Name)"
                                }
                                $OutObj | Sort-Object -Property 'Name' | Table @TableParams
                            }
                            if ($UpdObj) {
                                Section -Style Heading4 $LocalizedData.MissingUpdatesHeading {
                                    Paragraph $LocalizedData.MissingUpdatesParagraph
                                    BlankLine
                                    $UpdObj
                                }
                                Paragraph $LocalizedData.healthCheck -Bold -Underline
                                BlankLine
                                Paragraph {
                                    Text $LocalizedData.securityBestPractices -Bold
                                    Text $LocalizedData.securityPatchBestPracticeText
                                }
                            }
                        } catch {
                            Write-PScriboMessage -IsWarning $_.Exception.Message
                        }
                    }
                }
            }
        } catch {
            Write-PScriboMessage -IsWarning "Backup Server Section: $($_.Exception.Message)"
        }
    }
    end {
        if ($PssSession) { Remove-PSSession -Session $PssSession }
        if ($CimSession) { Remove-CimSession $CimSession }
        Show-AbrDebugExecutionTime -End -TitleMessage 'Backup Server Inventory Summary'
    }

}