Note du 08/08/2022: Write-PSLog v2 arrive bientôt, restez attentifs 🙂

Un bon système de log peut s’avérer indispensable pour certains scripts.

Avec le temps, ne trouvant pas de système vraiment adapté à mes besoins, j’ai créé mon propre système.

Ce que je met à votre disposition, c’est la version intermédaire de mon système, la version avancée n’étant pas complètement terminée (Les principales différences sont de pouvoir sortir des logs en XML optimisés pour CMTrace et la gestion des anciens logs (limitations à x MB ou à x logs)).

Voici la fonction:

function Write-PSLog {
    [CmdletBinding()]
    param (
        # Switch to specify to create a log
        [Parameter(
            Mandatory = $true,
            Position = 0,
            ParameterSetName = "LogCreation"
        )]
        [switch]
        $Create = $false,

        # Path of the log to create
        [Parameter(
            Mandatory = $True,
            Position = 1,
            ParameterSetName = "LogCreation"
        )]
        [string]
        $Path,

        # Allow to filter logged information type
        [Parameter(
            Mandatory = $false,
            Position = 2,
            ParameterSetName = "LogCreation"
        )]
        [ValidateSet('Minimum', 'Medium', 'Full')]
        [string]
        $LogLevel = "Full",

        # Allow to filter display information type
        [Parameter(
            Mandatory = $false,
            Position = 3,
            ParameterSetName = "LogCreation"
        )]
        [ValidateSet('None', 'Minimum', 'Medium', 'Full')]
        [String]
        $DisplayLevel = "Full",

        # Specify to don't overwrite existing log
        [Parameter(
            Mandatory = $false,
            Position = 4,
            ParameterSetName = "LogCreation" 
        )]
        [switch]
        $Append = $false,

        # Message you want to log
        [Parameter(
            Mandatory = $True,
            Position = 0, 
            ParameterSetName = "Message"
        )]
        [string]
        $Message,

        # Type of log entry
        [Parameter(
            Mandatory = $false,
            Position = 1,
            ParameterSetName = "Message"
        )]
        [ValidateSet('Info', 'Warning', 'Critical', 'Error')]
        [string]
        $Type = "Info",

        # Allow you to input an error object
        [Parameter(
            Mandatory = $true,
            Position = 0,
            ParameterSetName = "ErrorObject"
        )]
        [System.Management.Automation.ErrorRecord]
        $ErrorObject,
        
        # Switch to specify to close log
        [Parameter(
            Mandatory = $true,
            Position = 0,
            ParameterSetName = "LogClose" 
        )]
        [switch]
        $Close = $false,

        # Allow you to open log file at log completion
        [Parameter(
            Mandatory = $false,
            Position = 1,
            ParameterSetName = "LogClose"
        )]
        [switch]
        $OpenLog = $false
    )
    
    begin {
        if ($PSCmdlet.ParameterSetName -eq "Message" -or $PSCmdlet.ParameterSetName -eq "ErrorObject") {
            $Base = "[" + $(Get-Date -Format "yyyy-MM-dd HH:mm:ss") + "]"
        }
        if ($PSCmdlet.ParameterSetName -eq "LogCreation") {
            $Path = $Path -creplace "\[DATE\]", $(Get-Date -Format "yyyyMMdd")
            $Path = $Path -creplace "\[TIME\]", $(Get-Date -Format "HHmmss")
            $Path = $Path -creplace "\[PID\]" , $PID 

            $StartTime = [datetime]::Now
        }
    }
    
    process {
        if ($PSCmdlet.ParameterSetName -eq "LogCreation") {
               
            $Parent = Split-Path -Path $Path -Parent
            if (!(Test-Path $Parent)) {
                $null = New-Item $Parent -ItemType Directory
            }
            if (!(Test-Path $Path)) {
                $null = New-Item $Path -ItemType File
            }

            $Head = "-" * 55 + "[Log Start]" + "-" * 54 + "`r`n" + `
                    " " * 44 + "Log started at : " + $(Get-Date $StartTime -Format "HH:mm:ss - dd/MM/yyyy") + "`r`n" + `
                    " " * 55 + "PID : " + $PID + "`r`n" + "-" * 120

            If ($Append) {
                Add-Content -Value $Head -Path $Path
            }
            else {
                Set-Content -Value $Head -Path $Path -Force
            }
        }
        elseif ($PSCmdlet.ParameterSetName -eq "Message") {
            $LogEntry = $Base + "[" + $Type + "]`t" + $Message 
        }
        elseif ($PSCmdlet.ParameterSetName -eq "ErrorObject") {
            $ToWrite = $ErrorObject.Exception.Message + `
                " [" + $ErrorObject.Exception.GetType().FullName + "] " + `
                "(ln:" + $ErrorObject.InvocationInfo.ScriptLineNumber + " col:" + $ErrorObject.InvocationInfo.OffsetInLine + ")"
            $LogEntry = $Base + "[Error]`t" + $ToWrite
        }
    }
    
    end {
        if ($PSCmdlet.ParameterSetName -eq "LogCreation") {
            $Global:PSLogSettings = [PSCustomObject]@{
                Path         = $Path;
                LogLevel     = $LogLevel;
                DisplayLevel = $DisplayLevel
                StartTime    = $StartTime
            }
        }
        elseif ($PSCmdlet.ParameterSetName -eq "Message" -or $PSCmdlet.ParameterSetName -eq "ErrorObject") {
            switch ($Global:PSLogSettings.LogLevel) {
                "Minimum" { 
                    if ($LogEntry -notmatch "\[Info\]" -and $LogEntry -notmatch "\[Warning\]") { Add-Content -Value $LogEntry -Path $Global:PSLogSettings.Path -Force } 
                }
                "Medium" {
                    if ($LogEntry -notmatch "\[Info\]") { Add-Content -Value $LogEntry -Path $Global:PSLogSettings.Path -Force } 
                }
                "Full" { Add-Content -Value $LogEntry -Path $Global:PSLogSettings.Path -Force }
            }
            switch ($Global:PSLogSettings.DisplayLevel) {
                "Minimum" {
                    if ($LogEntry -notmatch "\[Info\]" -and $LogEntry -notmatch "\[Warning\]") { Write-Host $LogEntry }
                }
                "Medium" { 
                    if ($LogEntry -notmatch "\[Info\]") { Write-Host $LogEntry }
                }
                "Full" { Write-Host $LogEntry }
            }
        }
        elseif ($PSCmdlet.ParameterSetName -eq "LogClose") {

            $TS = New-TimeSpan $Global:PSLogSettings.StartTime -End $([datetime]::Now)

            $Foot = "-" * 120 + "`r`n"        + `
                    " " * 46  + "Completed in : " + $TS.Days + "d " + $TS.Hours + "h " + $TS.Minutes + "m " + $TS.Seconds + "s " + $TS.Milliseconds + "ms`r`n" + `
                    "-" * 55  + "[Log Close]" + "-" * 54 + "`r`n"           
            Add-Content -Value $Foot -Path $Global:PSLogSettings.Path -Force
            If ($OpenLog) {
                notepad.exe $Global:PSLogSettings.Path
            }
        }
    }
}

C’est un fameux pavé, mais très simple à utiliser.

Il fonctionne en 3 étapes:

  • Création (On créé le log)
  • Remplissage (On ajoute toutes les entrées que l’on souhaite dans le log manuellement ou on récupère un ErrorObject)
  • Clôture (On clôture le log)

Création

Syntaxe :

Write-PSLog [-Create] [-Path] <string> [[-LogLevel] {Minimum | Medium | Full}] [[-DisplayLevel] {None | Minimum | Medium | Full}] [[-Append]] [<CommonParameters>]

-Create

Ce paramètre est obligatoire pour déclencher la création du fichier de log ou son initialisation dans le cas d’un Append (voir plus bas)

-Path

Le chemin de votre fichier de log, ici vous avez la possibilité d’utiliser des tags :

  • [DATE] : Remplacé par la date au format “yyyyMMdd” (ex: le 26 juin 2018 devient 20180626).
  • [TIME] : Remplacé par l’heure courante au format « HHmmss » (ex : 18h 08m 04s devient 180804).
  • [PID] : Remplacé par le contenu de la variable $PID qui est l’identifiant de votre processus powershell.

-LogLevel

Ce paramètre permet de choisir les types d’informations inscrites dans le fichier de log, ce paramètre n’impact en rien l’affiche des informations dans la console. Trois niveaux de réglages sont possibles :

  • Minimum : Log uniquement dans le fichiers les erreurs (error) et les erreurs critiques (critical).
  • Medium : Identique au minimum mais log aussi les avertissements (Warning).
  • Full : Log tout, les erreurs, les erreurs critiques.

-DisplayLevel

Ce paramètre ne concerne pas ce qui est écrit dans le fichier de log mais ce qui est affiché dans la console. Ici 4 niveaux de réglages sont disponibles :

  • None : Aucune entrée de log n’est affichée dans la console.
  • Minimum : Seules les entrées de type Critical ou Error sont affichées dans la console.
  • Medium : Identique au minimum mais les entrées de type Warning sont aussi affichées.
  • Full : Affiche tous les types d’entrées dans la console

-Append

Si ce paramètre est spécifié et si un fichier de log du même nom existe, ce dernier sera complété au lieu d’être écrasé.

Exemples :

Exemple 1

Write-PSLog -Create -Path "$PSScriptRoot\log\[DATE]\[TIME]_MyApplication.log"

On créé un fichier de log avec des tags.

Le displaylevel ainsi que le loglevel n’étant pas précisés, c’est leur valeur par défaut qui est reprise, à savoir « Full » pour les deux.

Etant donné que Append n’est pas non plus spécifié, si un log du même nom existe, il sera écrasé sans avertissements.

Exemple 2

Write-PSLog -Create -Path C:\Temp\MyApplication.log -DisplayLevel None

Ici le fichier de log sera créé et complété mais aucune entrée de log ne sera affichée dans la console.

Exemple 3

Write-PSLog -Create -Path C:\Temp\MyLog.log -LogLevel Minimum -Append

Si un fichier du même nom existe, il sera complété. Uniquement les erreurs et les erreurs critiques seront inscrites dans le log.

Remplissage manuel

Syntaxe :

Write-PSLog [-Message] <string> [[-Type] {Info | Warning | Critical | Error}] [<CommonParameters>]

-Message

Le message que vous voulez inscrire dans le log et/ou dans la console.

-Type

Ce paramètre vous permet de préciser le type d’entrée, les possibilités sont les suivantes :

  • Info (Valeur par défaut)
  • Warning
  • Error
  • Critical

Exemples :

Exemple 1

Write-PSlog "Mon message"

Créé une entrée de type « Info ».

Exemple 2

Write-PSLog "Un probleme est survenu" Error

Créé une entrée de type Error avec le message spécifié.

Remplissage avec un ErrorObject

Syntaxe :

Write-PSLog [-ErrorObject] <ErrorRecord> [<CommonParameters>]

Exemples :

Exemple 1

$ErrorActionPreference = "Stop"

Try
{
    1/0
}
Catch
{
    Write-PSLog $_
}

On fait une division par 0 pour généré une erreur qu’on récupère dans le fichier log.

Clôture

Syntaxe :

Write-PSLog [-Close] [[-OpenLog]] [<CommonParameters>]

-Close

Ce paramètre est obligatoire pour déclencher la fermeture du log.

-OpenLog

Si ce paramètre est spécifié, le fichier de log sera ouvert à la clôture.

Exemples :

Exemple 1

Write-PSLog -Close -OpenLog

On clôture et on ouvre le log.

N’hésitez pas à  me contacter en cas de question.

Catégories : Ressources

0 commentaire

Laisser un commentaire

Emplacement de l’avatar

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *