switc.configmgr.LogReader.psm1
function read-SWITCCMLog { [CmdletBinding( DefaultParameterSetName="standard" )] param ( [parameter(ParameterSetName="standard")] [parameter(ParameterSetName="export")] [string]$ContainsFilter, [parameter(ParameterSetName="standard")] [parameter(ParameterSetName="export")] [string]$ConfigMgrLogFile = "", [parameter(ParameterSetName="standard")] [parameter(ParameterSetName="export")] [string[]]$ErrorIndicators = @( "error", "failed", "failure", "fail", "exception" ), [parameter(ParameterSetName="standard")] [parameter(ParameterSetName="export")] [string[]]$WarningIndicators = @( "warning", "warn", "not to verify the signature of the scripts" ), [parameter(ParameterSetName="standard")] [parameter(ParameterSetName="export")] [string[]]$ErrorWarningExluceIndicators = @( "error code 0", "ContinueOnError=''", "Sending warning status message", "_SMSTSStatusSendFailed", "OSDDownloadContinueDownloadOnError", "ContinueOnError:" ), [parameter(ParameterSetName="export")][switch]$ExportAsJson ) $ErrorActionPreference = "stop" enum MessageType { error warning info } $private:CharacterTranslationTable = @{ "$([char]38)"='&'; # Char:& "$([char]34)"='"'; # Char:" "$([char]39)"='''; # Char:' "$([char]60)"='<'; # Char:< "$([char]62)"='>'; # Char:> #"$([char]59)"=';'; # Char:; #"$([char]33)"='!'; # Char:! #"$([char]35)"='#'; # Char:# #"$([char]36)"='$'; # Char:$ #"$([char]37)"='%'; # Char:% #"$([char]40)"='('; # Char:( #"$([char]41)"=')'; # Char:) #"$([char]42)"='*'; # Char:* #"$([char]43)"='+'; # Char:+ #"$([char]44)"=','; # Char:, #"$([char]46)"='.'; # Char:. #"$([char]47)"='/'; # Char:/ #"$([char]92)"='\'; # Char:\ #"$([char]58)"=':'; # Char:: #"$([char]61)"='='; # Char:= #"$([char]63)"='?'; # Char:? #"$([char]91)"='['; # Char:[ #"$([char]93)"=']'; # Char:] #"$([char]123)"='{'; # Char:{ #"$([char]125)"='}'; # Char:} #"$([char]124)"='|'; # Char:| } $XML = [Xml]::new() $Private:Content = Get-Content -path $ConfigMgrLogFile :fileLineLoop Foreach ($FileLineEntry in $Content) { <# old: $FileLineEntry = $FileLineEntry.Replace("![LOG[","MessageEntry>").Replace("]LOG]!><","</MessageEntry><MessageAttributes ") [int]$MessageStartIndex = $FileLineEntry.IndexOf('<MessageEntry>') + 14 [int]$MessageEndIndex = $FileLineEntry.IndexOf('</MessageEntry>') #> If (-not ([string]::IsNullOrEmpty($FileLineEntry) -or ([string]::IsNullOrWhiteSpace($FileLineEntry)))) { If ($FileLineEntry.startsWith("Parsing",[System.StringComparison]::OrdinalIgnoreCase)) { $FileLineEntry = "<![LOG[" + $FileLineEntry } If ($FileLineEntry -ieq "<![LOG[") { continue fileLineLoop } [string]$FileLineEntry = "$($FileLineEntry.Substring(0,($FileLineEntry.Length -1)))/>" [int]$MessageStartIndex = 0 [int]$MessageEndIndex = 0 [int]$MessageAttributeStart = 0 [int]$messageLengthIndex = 0 If ($FileLineEntry.Contains("<![LOG[",[System.StringComparison]::OrdinalIgnoreCase)) { [int]$MessageStartIndex = $FileLineEntry.IndexOf('<![LOG[') + 7 [int]$MessageEndIndex = $FileLineEntry.IndexOf(']LOG]!>') [int]$MessageAttributeStart = $FileLineEntry.IndexOf(']LOG]!><') + 8 [string]$MesssageAttributeEntry = "<MessageAttributes " + $FileLineEntry.Substring($MessageAttributeStart) If (($MessageEndIndex - $MessageStartIndex) -gt ($FileLineEntry.Length - $MessageStartIndex)) { $messageLengthIndex = ($FileLineEntry.Length - $MessageStartIndex) } Else { $messageLengthIndex = ($MessageEndIndex - $MessageStartIndex) } if (0 -gt $messageLengthIndex) { $messageLengthIndex = 0 } [string]$MessageEntry = $FileLineEntry.Substring($MessageStartIndex,$messageLengthIndex) } Else { $MessageEntry = $FileLineEntry } #[string]$MessageEntry = $MessageEntry.Replace(([char]59),$private:CharacterTranslationTable[([char]59)]) [string]$MessageEntry = $MessageEntry.Replace(([char]38),$private:CharacterTranslationTable[([char]38)]) foreach ($Character in $private:CharacterTranslationTable.Keys) { If (-not ($Character -in @( [char]38, [char]59 ))) { $MessageEntry = $MessageEntry.Replace($Character,$private:CharacterTranslationTable[$Character]) } } #old: $FileLineEntry = "<LogEntry><MessageEntry>$($MessageEntry)</MessageEntry>$($FileLineEntry.Substring($FileLineEntry.IndexOf('<MessageAttributes')))</LogEntry>" $FileLineEntry = '<?xml version="1.0" encoding="UTF-8"?>' + "<LogEntry><MessageEntry>$($MessageEntry)</MessageEntry>$($MesssageAttributeEntry)</LogEntry>" Try { $XML.LoadXml($FileLineEntry) } catch { Try { $FileLineEntry = '<?xml version="1.0" encoding="UTF-8"?>' + "<LogEntry><MessageEntry>ERROR CONVERTING MESSAGE!</MessageEntry>$($MesssageAttributeEntry)</LogEntry>" $XML.LoadXml($FileLineEntry) } Catch { continue fileLineLoop } } If (-not ([string]::IsNullOrEmpty($XML.LogEntry.MessageAttributes.Time))) { $XML.LogEntry.MessageAttributes.RemoveAttribute("Time") $XML.LogEntry.MessageAttributes.SetAttribute("Time","$($XML.LogEntry.MessageAttributes.Time.split('-')[0])") $private:TimeValue = $XML.LogEntry.MessageAttributes.Time.split('-')[0] } If (-not ([string]::IsNullOrEmpty($XML.LogEntry.MessageAttributes.date))) { $private:DateValue = $XML.LogEntry.MessageAttributes.date } # $($XML.LogEntry.MessageAttributes.date) $() If (-not ([string]::IsNullOrEmpty($private:DateValue) -or ([string]::IsNullOrEmpty($private:TimeValue)))) { [DateTime]$private:MessageEntryDateTime = [DateTime]"$($private:DateValue) $($private:TimeValue)" $XML.LogEntry.MessageAttributes.RemoveAttribute("MessageLogged") $XML.LogEntry.MessageAttributes.SetAttribute("MessageLogged",[DateTime]$private:MessageEntryDateTime) $XML.LogEntry.MessageAttributes.RemoveAttribute("MessageLoggedFileTime") $XML.LogEntry.MessageAttributes.SetAttribute("MessageLoggedFileTime",[DateTime]$Private:MessageEntryDateTime.ToFileTime()) } $XML.LogEntry.MessageAttributes.RemoveAttribute("MessageType") $XML.LogEntry.MessageAttributes.SetAttribute("MessageType","$([MessageType]::info)") # Warning includes Foreach ($WarningIndicator in $WarningIndicators) { If ($XML.LogEntry.MessageEntry.contains($WarningIndicator,[System.StringComparison]::OrdinalIgnoreCase)) { $XML.LogEntry.MessageAttributes.RemoveAttribute("MessageType") $XML.LogEntry.MessageAttributes.SetAttribute("MessageType","$([MessageType]::warning)") } } # Error includes Foreach ($ErrorIndicator in $ErrorIndicators) { If ($XML.LogEntry.MessageEntry.contains($ErrorIndicator,[System.StringComparison]::OrdinalIgnoreCase)) { $XML.LogEntry.MessageAttributes.RemoveAttribute("MessageType") $XML.LogEntry.MessageAttributes.SetAttribute("MessageType","$([MessageType]::error)") } } # exludes Foreach ($ExcludeIndicator in $ErrorWarningExluceIndicators) { If ($XML.LogEntry.MessageEntry.contains($ExcludeIndicator,[System.StringComparison]::OrdinalIgnoreCase)) { $XML.LogEntry.MessageAttributes.RemoveAttribute("MessageType") $XML.LogEntry.MessageAttributes.SetAttribute("MessageType","$([MessageType]::info)") } } if (-not ($ExportAsJson)) { If (-not [string]::IsNullOrEmpty($ContainsFilter)) { If (-not ($XML.LogEntry.MessageEntry.contains($ContainsFilter,[System.StringComparison]::OrdinalIgnoreCase))) { continue fileLineLoop } } Write-Host "$($XML.LogEntry.MessageAttributes.MessageLogged) " -ForegroundColor Gray -NoNewline Write-Host "| " -NoNewline switch ($XML.LogEntry.MessageAttributes.MessageType) { "$([MessageType]::error)" { Write-Host -Object "$($XML.LogEntry.MessageEntry)" ` -ForegroundColor $GLOBAL:HOST.PrivateData.ErrorForegroundColor } "$([MessageType]::warning)" { Write-Host -Object "$($XML.LogEntry.MessageEntry)" ` -ForegroundColor $GLOBAL:HOST.PrivateData.WarningForegroundColor } "$([MessageType]::info)" { Write-Host -Object "$($XML.LogEntry.MessageEntry)" } } } } } } Export-ModuleMember -Function "read-SWITCCMLog" |