EZLog.psm1
#Requires -Version 5.1 $ErrorActionPreference = 'Stop' Set-PSDebug -Strict Add-Type -TypeDefinition @" public enum MsgCategory { INF = 0, WAR = 1, ERR = 2 } public enum Interval { Daily = 0, Monthly = 2, Yearly = 3 } "@ Function Write-EZLog { [cmdletBinding(DefaultParameterSetName="set2", SupportsShouldProcess=$False)] PARAM ( [parameter(Mandatory=$true, ParameterSetName="set2", ValueFromPipeline=$false, position=0)] [MsgCategory]$Category, [parameter(Mandatory=$true, ParameterSetName="set2", ValueFromPipeline=$false, position=1)] [Alias("Msg")] [String]$Message, [parameter(Mandatory=$true, ParameterSetName="set1", ValueFromPipeline=$false)] [Switch]$Header, [parameter(Mandatory=$true, ParameterSetName="set3", ValueFromPipeline=$false)] [Switch]$Footer, [parameter(Mandatory=$true, ValueFromPipeline=$false)] [String]$LogFile, [parameter(Mandatory=$false, ValueFromPipeline=$false)] [Char]$Delimiter = $( if ((Get-Culture).TextInfo.ListSeparator -eq ' ') {','} else {(Get-Culture).TextInfo.ListSeparator}), [parameter(Mandatory=$false, ValueFromPipeline=$false)] [Switch]$ToScreen=$false ) $Color = 'Cyan' $currentScriptName = $myinvocation.ScriptName $StartDate_str = Get-Date -UFormat "%Y-%m-%d %H:%M:%S" if ($isLinux -or $isMacOS) { $currentUser = $ENV:USER $currentComputer = uname -n $OSName = uname -s $OSArchi = uname -m $StrTerminator = "`r" } else { $currentUser = $ENV:USERDOMAIN + '\' + $ENV:USERNAME $currentComputer = $ENV:COMPUTERNAME $WmiInfos = Get-CimInstance win32_operatingsystem $OSName = $WmiInfos.caption $OSArchi = $WmiInfos.OSArchitecture $StrTerminator = "`r`n" } Switch ($PsCmdlet.ParameterSetName) { "set1" # Header { $Message = "+----------------------------------------------------------------------------------------+{0}" $Message += "Script fullname : $currentScriptName{0}" $Message += "When generated : $StartDate_str{0}" $Message += "Current user : $currentUser{0}" $Message += "Current computer : $currentComputer{0}" $Message += "Operating System : $OSName{0}" $Message += "OS Architecture : $OSArchi{0}" $Message += "+----------------------------------------------------------------------------------------+{0}" $Message += "{0}" $Message = $Message -f $StrTerminator # Log file creation. [VOID] (New-Item -ItemType File -Path $LogFile -Force) Add-Content -Path $LogFile -Value $Message -NoNewline break } "set2" # Body { $date = Get-Date -UFormat "%Y-%m-%d %H:%M:%S" switch ($Category) { INF { $Message = ("$date{0} INF{0} $Message{1}" -f $Delimiter, $StrTerminator); $Color = 'Cyan' ; break } WAR { $Message = ("$date{0} WAR{0} $Message{1}" -f $Delimiter, $StrTerminator); $Color = 'Yellow' ; break } ERR { $Message = ("$date{0} ERR{0} $Message{1}" -f $Delimiter, $StrTerminator); $Color = 'Red' ; break } } Add-Content -Path $LogFile -Value $Message -NoNewLine break } "set3" # Footer { # Extracting start date from the file header [VOID]( (Get-Content $LogFile -TotalCount 3)[-1] -match '^When generated\s*: (?<date>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})$' ) if ($null -eq $Matches.date) { throw "Cannot get the start date from the header. Please check if the file header is correctly formatted." } $StartDate = [DateTime]$Matches.date $EndDate = Get-Date $EndDate_str = Get-Date $EndDate -UFormat "%Y-%m-%d %H:%M:%S" $duration_TotalSeconds = [int](New-TimeSpan -Start $StartDate -End $EndDate | Select-Object -ExpandProperty TotalSeconds) $duration_TotalMinutes = (New-TimeSpan -Start $StartDate -End $EndDate | Select-Object -ExpandProperty TotalMinutes) $duration_TotalMinutes = [MATH]::Round($duration_TotalMinutes, 2) $Message = "{0}" $Message += "+----------------------------------------------------------------------------------------+{0}" $Message += "End time : $EndDate_str{0}" $Message += "Total duration (seconds) : $duration_TotalSeconds{0}" $Message += "Total duration (minutes) : $duration_TotalMinutes{0}" $Message += "+----------------------------------------------------------------------------------------+{0}" $Message = $Message -f $StrTerminator # Append the footer to the log file Add-Content -Path $LogFile -Value $Message -NoNewLine break } } # End switch if ($ToScreen) { Write-Host $Message -ForegroundColor $Color } } Function Get-Log { Param ($file) $content = Get-Content -Path $file $index = 0 $sepPos = @() foreach ($line in $content) { if ($line -like '+-*-+') { $sepPos += $index } $index++ } $result = (Get-Content $file)[(($SepPos[1])+1)..(($SepPos[2])-1)] $result -ne '' # Blank lines exclusion } Function ConvertFrom-EZlog { Param ( [parameter(Mandatory=$true, ValueFromPipeline=$true, position=0)] [Alias("Path")] [string]$FilePath ) begin { } process { $result = @{ Header = @{ ScriptFullname = '' WhenGenerated = '' CurrentUser = '' CurrentComputer = '' OperatingSystem = '' OSArchitecture = '' } Events = @() Footer = @{ EndTime = '' Duration = '' } } $header = Get-Content -Path $FilePath | Select-Object -Skip 1 -First 6 $result.Header.ScriptFullname = $( $null = $header[0] -match '(?<Name>.+?)(:\s{1})(?<Value>.+)?' if ( $matches ) { $matches.Value } ) $result.Header.WhenGenerated = $( $null = $header[1] -match '(?<Name>.+?)(:\s{1})(?<Value>.+)?' if ( $matches ) { [DateTime]($matches.Value) } ) $result.Header.CurrentUser = $( $null = $header[2] -match '(?<Name>.+?)(:\s{1})(?<Value>.+)?' if ( $matches ) { $matches.Value } ) $result.Header.CurrentComputer = $( $null = $header[3] -match '(?<Name>.+?)(:\s{1})(?<Value>.+)?' if ( $matches ) { $matches.Value } ) $result.Header.OperatingSystem = $( $null = $header[4] -match '(?<Name>.+?)(:\s{1})(?<Value>.+)?' if ($matches) { $matches.Value } ) $result.Header.OSArchitecture = $( $null = $header[5] -match '(?<Name>.+?)(:\s{1})(?<Value>.+)?' if ($matches) { $matches.Value } ) $footer = Get-Content -Path $FilePath | Select-Object -Skip 1 -Last 3 $result.Footer.EndTime = $( $null = $footer[0] -match '(?<Name>.+?)(:\s{1})(?<Value>.+)?' if ($matches) { [DateTime]($matches.Value) } ) $result.Footer.Duration = New-TimeSpan -Start $result.Header.WhenGenerated -End $result.Footer.EndTime $LogMessages = Get-Log -file $FilePath $separator = $LogMessages[0][19] foreach ($log in $LogMessages) { $res = $log -split $separator $result.Events += [PSCustomObject]@{ Date = $res[0] -as [DateTime] Category = $res[1].Trim() Message = $res[2].Trim() } } } end { $result } } Function Invoke-EZLogRotation { [cmdletBinding(DefaultParameterSetName='set1', SupportsShouldProcess=$False)] PARAM ( [parameter(Mandatory=$true, position=0)] [String]$Path, [parameter(Mandatory=$true, position=1)] [String]$Filter, [parameter(Mandatory=$true, ParameterSetName="set1", ValueFromPipeline=$false)] [Int]$Newest, [parameter(Mandatory=$true, ParameterSetName="set2", ValueFromPipeline=$false, position=1)] [Interval]$Interval, [parameter(Mandatory=$false)] [ValidateScript({$_ -like '*.zip'})] [String]$ArchiveTo, [parameter(Mandatory=$false)] [Switch]$OverwriteArchive ) Switch ($PSCmdlet.ParameterSetName) { 'Set1' { $filesToRemove = Get-ChildItem -Path $Path -Filter $Filter | Sort-Object -Property LastWriteTime -Descending | Select-Object -Skip $Newest } 'Set2' { Switch ($Interval) { 'Daily' { $filesToKeep = Get-ChildItem -Path $Path -Filter $Filter | Where-Object { $_.LastWriteTime.Year -eq (Get-Date).Year -and $_.LastWriteTime.Month -eq (Get-Date).Month -and $_.LastWriteTime.Day -eq (Get-Date).Day } $filesToRemove = Get-ChildItem "$Path\$Filter" -Exclude $filesToKeep Break } <# 'Weekly' { $filesToKeep = Get-ChildItem -Path $Path -Filter $Filter | Where-Object { $_.LastWriteTime -ge (Get-FirstDayOfWeekDate) -and $_.LastWriteTime -le (Get-Date) } $filesToRemove = Get-ChildItem "$Path\$Filter" -Exclude $filesToKeep Break } #> 'Monthly' { $filesToKeep = Get-ChildItem -Path $Path -Filter $Filter | Where-Object { $_.LastWriteTime -ge (Get-FirstDayOfMonthDate) -and $_.LastWriteTime -le (Get-Date) } $filesToRemove = Get-ChildItem "$Path\$Filter" -Exclude $filesToKeep Break } 'Yearly' { $filesToKeep = Get-ChildItem -Path $Path -Filter $Filter | Where-Object { $_.LastWriteTime.Year -eq (Get-Date).Year } $filesToRemove = Get-ChildItem "$Path\$Filter" -Exclude $filesToKeep Break } } } } if ($ArchiveTo -and $OverwriteArchive) { $filesToRemove | Compress-Archive -DestinationPath $ArchiveTo -CompressionLevel Optimal -Force } elseif ($ArchiveTo) { $filesToRemove | Compress-Archive -DestinationPath $ArchiveTo -CompressionLevel Optimal -Update } $filesToRemove | Remove-Item } Function Get-FirstDayOfWeek { (Get-Culture).DateTimeFormat.FirstDayOfWeek } Function Get-FirstDayOfWeekDate { Param ( [Datetime]$date = (Get-Date) ) if ( ( (Get-FirstDayOfWeek) -eq [DayOfWeek]::Monday) -and ($date.DayOfWeek -eq [DayOfWeek]::Sunday) ) { $nbJoursARetirer = 6 } elseif ( ( (Get-FirstDayOfWeek) -eq [DayOfWeek]::Sunday) -and ($date.DayOfWeek -eq [DayOfWeek]::Sunday) ) { $nbJoursARetirer = 0 } else { $nbJoursARetirer = [int]$date.DayOfWeek - [int](Get-FirstDayOfWeek) } $date = $date.AddDays(-$nbJoursARetirer) New-Object -TypeName datetime $date.Year, $date.Month, $date.Day, 0, 0, 0, 0 } Function Get-FirstDayOfMonthDate { Param ( [Datetime]$date = (Get-Date) ) New-Object -TypeName datetime $date.Year, $date.Month, 1, 0, 0, 0, 0 } |