Public/Write-CCMLogEntry.ps1
Function Write-CCMLogEntry { <# .DESCRIPTION Write CMTrace friendly log files with options for log rotation .EXAMPLE $Bias = (Get-CimInstance -ClassName Win32_TimeZone).Bias $FileName = "myscript_" + (Get-Date -Format 'yyyy-MM-dd_HH-mm-ss') + ".log" Write-CCMLogEntry -Value "Writing text to log file" -Severity 1 -Component "Some component name" -FileName $FileName -Folder "C:\Windows\temp" -Bias $Bias -Enable -MaxLogFileSize 1MB -MaxNumOfRotatedLogs 3 #> param ( [parameter(Mandatory = $true, HelpMessage = 'Value added to the log file.')] [ValidateNotNullOrEmpty()] [string]$Value, [parameter(Mandatory = $false, HelpMessage = 'Severity for the log entry. 1 for Informational, 2 for Warning and 3 for Error.')] [ValidateNotNullOrEmpty()] [ValidateSet('1', '2', '3')] [string]$Severity = 1, [parameter(Mandatory = $false, HelpMessage = "Stage that the log entry is occuring in, log refers to as 'component'.")] [ValidateNotNullOrEmpty()] [string]$Component, [parameter(Mandatory = $true, HelpMessage = 'Name of the log file that the entry will written to.')] [ValidateNotNullOrEmpty()] [string]$FileName, [parameter(Mandatory = $true, HelpMessage = 'Path to the folder where the log will be stored.')] [ValidateNotNullOrEmpty()] [string]$Folder, [parameter(Mandatory = $false, HelpMessage = 'Set timezone Bias to ensure timestamps are accurate.')] [ValidateNotNullOrEmpty()] [int32]$Bias, [parameter(Mandatory = $false, HelpMessage = 'Maximum size of log file before it rolls over. Set to 0 to disable log rotation.')] [ValidateNotNullOrEmpty()] [int32]$MaxLogFileSize = 5MB, [parameter(Mandatory = $false, HelpMessage = 'Maximum number of rotated log files to keep. Set to 0 for unlimited rotated log files.')] [ValidateNotNullOrEmpty()] [int32]$MaxNumOfRotatedLogs = 0, [parameter(Mandatory = $false, HelpMessage = 'A switch that enables the use of this function.')] [ValidateNotNullOrEmpty()] [switch]$Enable ) If ($Enable) { # Determine log file location $LogFilePath = Join-Path -Path $Folder -ChildPath $FileName If ((([System.IO.FileInfo]$LogFilePath).Exists) -And ($MaxLogFileSize -ne 0)) { # Get log size in bytes $LogFileSize = ([System.IO.FileInfo]$LogFilePath).Length If ($LogFileSize -ge $MaxLogFileSize) { # Get log file name without extension $LogFileNameWithoutExt = $FileName -replace ([System.IO.Path]::GetExtension($FileName)) # Get already rolled over logs $AllLogs = Get-ChildItem -Path $Folder -Name "$($LogFileNameWithoutExt)_*" -File # Sort them numerically (so the oldest is first in the list) $AllLogs = Sort-Object -InputObject $AllLogs -Descending { $_ -replace '_\d+\.lo_$' }, { [Int]($_ -replace '^.+\d_|\.lo_$') } -ErrorAction Ignore ForEach ($Log in $AllLogs) { # Get log number $LogFileNumber = [int32][Regex]::Matches($Log, "_([0-9]+)\.lo_$").Groups[1].Value switch (($LogFileNumber -eq $MaxNumOfRotatedLogs) -And ($MaxNumOfRotatedLogs -ne 0)) { $true { # Delete log if it breaches $MaxNumOfRotatedLogs parameter value [System.IO.File]::Delete("$($Folder)\$($Log)") } $false { # Rename log to +1 $NewFileName = $Log -replace "_([0-9]+)\.lo_$", "_$($LogFileNumber+1).lo_" [System.IO.File]::Copy("$($Folder)\$($Log)", "$($Folder)\$($NewFileName)", $true) } } } # Copy main log to _1.lo_ [System.IO.File]::Copy($LogFilePath, "$($Folder)\$($LogFileNameWithoutExt)_1.lo_", $true) # Blank the main log $StreamWriter = New-Object -TypeName System.IO.StreamWriter -ArgumentList $LogFilePath, $false $StreamWriter.Close() } } # Construct time stamp for log entry switch -regex ($Bias) { '-' { $Time = [string]::Concat($(Get-Date -Format 'HH:mm:ss.fff'), $Bias) } Default { $Time = [string]::Concat($(Get-Date -Format 'HH:mm:ss.fff'), '+', $Bias) } } # Construct date for log entry $Date = (Get-Date -Format 'MM-dd-yyyy') # Construct context for log entry $Context = $([System.Security.Principal.WindowsIdentity]::GetCurrent().Name) # Construct final log entry $LogText = [string]::Format('<![LOG[{0}]LOG]!><time="{1}" date="{2}" component="{3}" context="{4}" type="{5}" thread="{6}" file="">', $Value, $Time, $Date, $Component, $Context, $Severity, $PID) # Add value to log file try { $StreamWriter = New-Object -TypeName System.IO.StreamWriter -ArgumentList $LogFilePath, 'Append' $StreamWriter.WriteLine($LogText) $StreamWriter.Close() } catch [System.Exception] { Write-Warning -Message "Unable to append log entry to $FileName file. Error message: $($_.Exception.Message)" } } } |