Public/ConvertFrom-NSPRichCopyLog.ps1

function ConvertFrom-NSPRichCopyLog {
    <#
    .SYNOPSIS
        Reads a Unicode RichCopy report and extracts dated records and error paths.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)][ValidateNotNullOrEmpty()][string]$Path,
        [ValidateSet('Unicode', 'UTF8', 'Default')][string]$Encoding = 'Unicode'
    )

    $resolved = (Resolve-Path -LiteralPath $Path -ErrorAction Stop).ProviderPath
    $raw = Get-Content -LiteralPath $resolved -Raw -Encoding $Encoding -ErrorAction Stop
    # RichCopy can continue an operation after CRLF and a comma. The original
    # parser joins those fragments before matching records.
    $normalized = [regex]::Replace($raw, '.\r\n,', '.')
    $lineRegex = New-Object System.Text.RegularExpressions.Regex((Get-NSPLogPattern RichCopyRecord), ([System.Text.RegularExpressions.RegexOptions]::Compiled), ([timespan]::FromSeconds(2)))
    $pathRegex = New-Object System.Text.RegularExpressions.Regex('(?<Error>.*?)(?<Path>[A-Za-z]:\\[^\r\n]*)$', ([System.Text.RegularExpressions.RegexOptions]::Compiled), ([timespan]::FromSeconds(2)))
    $lineNumber = 0
    foreach ($line in ($normalized -split '\r?\n')) {
        $lineNumber++
        $match = $lineRegex.Match($line)
        if (-not $match.Success) { continue }
        $operation = $match.Groups['Operation'].Value
        $errorPath = $null
        $errorMessage = $null
        if ($match.Groups['Code'].Value -ne '0') {
            $pathMatch = $pathRegex.Match($operation)
            if ($pathMatch.Success) {
                $errorPath = $pathMatch.Groups['Path'].Value
                $errorMessage = $pathMatch.Groups['Error'].Value.Trim()
            }
        }
        [pscustomobject]@{
            LineNumber = $lineNumber
            Date = $match.Groups['Date'].Value
            Time = $match.Groups['Time'].Value
            Code = $match.Groups['Code'].Value
            Operation = $operation
            ErrorMessage = $errorMessage
            ErrorPath = $errorPath
        }
    }
}