Public/Get-PdqInventoryScanErrors.ps1

<#
.SYNOPSIS
Retrieves scan errors from the PDQ Inventory database.

.DESCRIPTION
By default, all errors will be output as an array of PSCustomObjects (up to -Limit).
-Group is great for seeing what your most frequent scan errors are.

.INPUTS
None.

.OUTPUTS
-Group | -DisableGroupSorting | Type
---------------------------------------------------------------------------
No | No | System.Management.Automation.PSCustomObject
Yes | No | System.Object[]
Yes | Yes | System.Collections.Hashtable

.EXAMPLE
Get-PdqInventoryScanErrors -Group -Limit 500
Retrieve 500 scan errors and group them.
#>

function Get-PdqInventoryScanErrors {

    [CmdletBinding()]
    param (
        # Remove computer names from the error messages, count the number of occurrences of each error message,
        # then output an array sorted by error message.
        [Switch]$Group,

        # Only effective if -Group is specified. Outputs a hashtable instead of a sorted array.
        [Switch]$DisableGroupSort,

        # The maximum number of errors to retrieve.
        [UInt32]$Limit = 10000,

        # The path to the currently active database will be retrieved by default.
        # You can use this parameter if you wish to run this function against a different database.
        [String]$DatabasePath
    )

    # This is just a guess. I have no idea what the oldest compatible version is.
    Assert-PdqMinimumVersion -Product 'Inventory' -MinimumVersion '1.0.0.0'

    $ScansWithErrorsQuery = @"
SELECT
    Computers.Name
    , Computers.HostName
    , ComputerScans.ComputerScanId
    , ComputerScans.Started
    , ComputerScans.Error
FROM
    ComputerScans
INNER JOIN
    Computers USING (ComputerId)
WHERE
    ComputerScans.Error != ''
ORDER BY
    ComputerScans.ComputerScanId DESC
LIMIT $Limit
"@


    $AllErrors = @{}

    Try {

        $CloseConnection = Open-PdqSqlConnection -Product 'Inventory' -DatabasePath $DatabasePath

        Invoke-SqlQuery -Query $ScansWithErrorsQuery -ConnectionName 'Inventory' -Stream | ForEach-Object {
            
            $Scan = $_
            [XML]$ScanError = $Scan.Error

            if ( $Group ) {

                # Remove computer names so messages will group.
                $ScanErrorMessage = $ScanError.Error.Message.Replace($Scan.HostName, 'Computer')
                
                $AllErrors.$ScanErrorMessage ++

            } else {

                # Format the final message.
                [PSCustomObject]@{
                    'Name'           = $Scan.Name
                    'ComputerScanId' = [UInt64]$Scan.ComputerScanId
                    'Started'        = [DateTime]$Scan.Started
                    'Error'          = $ScanError.Error.Message
                }

            }

        }

        if ( $Group ) {

            if ( $DisableGroupSort ) {

                $AllErrors

            } else {
            
                $AllErrors.GetEnumerator() | Sort-Object Name | Format-Table Value, Name

            }

        }

    } Finally {

        Close-PdqSqlConnection -Product 'Inventory' -CloseConnection $CloseConnection

    }

}