Logging für PowerShell-Skripte

Letzte Aktualisierung am 01.01.2023, 14:01:57 Uhr

Zur Zeit beschäftige ich mich wieder intensiver mit PowerShell, genauer gesagt mit der Entwicklung von Skripten für wiederkehrenden administrativen Aufgaben. Bisher waren meine Skripte überschaubar und schlicht gehalten. Einen strukturierten Aufbau der Skripts war bisher mehr oder weniger immer gegeben. Mit zu nehmender Komplexität und großem Umfang stellt man schnell fest, dass es ohne Logging kaum möglich ist einen vermeidlichen Fehler ohne großen Zeitaufwand zu analysieren und einzugrenzen.

Daher habe ich mich entschlossen eine Funktion entwerfen, die folgende Anforderungen abdecken soll:

  • Datum und Zeit an dem der  jeweilige Befehl/Aktion ausgeführt wird.
  • Verschiedene Loglevel mit dazugehörigen Farben in der PowerShell Konsole.
  • Ausgabe der Meldungen sowohl in der PowerShell Konsole als auch in eine Protokolldatei mit einem Befehl (Vermeidung von Overhead im Quellcode).
  • Benutzername und Domäne bzw. Computername, auf dem das Skript gelaufen ist, sollen festgehalten werden.
  • Dateiname als auch Speicherort soll über Variable änderbar sein, ohne großartig den Quellcode anpassen zu müssen.

Folgendes PowerShell-Schnipsel ist entstanden:

#----------------------------------------------------------[Declarations]----------------------------------------------------------
# function Write-Log
[string] $strLogfilePath = "C:\Temp"
[string] $strLogfileDate = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
[string] $strLogfileNamePrefix = "Log_"
[string] $strLogfileName = $($strLogfileNamePrefix + $strLogfileDate + ".log")
[string] $strLogfile = $strLogfilePath + "\" + $strLogfileName

#-----------------------------------------------------------[Functions]------------------------------------------------------------

function Write-Log {
    [CmdletBinding()]
    param (
        [Parameter(
            Mandatory=$true,
            Position=0)]
        [ValidateNotNullOrEmpty()]
        [string] $LogText = "",

        [Parameter(Mandatory=$false)]
        [ValidateNotNullOrEmpty()]
        [ValidateSet('Info','Success','Warning','Error')]
        [string] $LogStatus= "Info",

        [Parameter(Mandatory=$false)]
        [switch] $Absatz,

        [Parameter(Mandatory=$false)]
        [switch] $EventLog
    )

    [string] $strLogdate = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    [string] $strTextColor = "White"
    [string] $strLogFileAbsatz = ""
    [string] $strLogFileHeader = ""

    # Add a header to logfile, if the logfile not exist
    If ( -not (Test-Path $strLogfile) ) {
        $strLogFileHeader = "$("#" * 75)`n"
        $strLogFileHeader += "{0,-21} {1,0}" -f "# Skript:", "$($MyInvocation.ScriptName)`n"
        $strLogFileHeader += "{0,-21} {1,0}" -f "# Startzeit:", "$(Get-Date -Format "dd.MM.yyyy HH:mm:ss")`n"
        $strLogFileHeader += "{0,-21} {1,0}" -f "# Startzeit:", "$(Get-Date -Format "dd.MM.yyyy HH:mm:ss")`n"
        $strLogFileHeader += "{0,-21} {1,0}" -f "# Ausführendes Konto:", "$([Security.Principal.WindowsIdentity]::GetCurrent().Name)`n"
        $strLogFileHeader += "{0,-21} {1,0}" -f "# Computername:", "$env:COMPUTERNAME`n"
        $strLogFileHeader += "$("#" * 75)`n"

        Write-Host $strLogFileHeader
        Add-Content -Path $strLogfile -Value $strLogFileHeader -Encoding UTF8
    }
   

    switch($LogStatus) {
        Info {
            $strTextColor = "White"
        }
        Success {
            $strTextColor = "Green"
        }
        Warning {
            $strTextColor = "Yellow"
        }
        Error {
            $strTextColor = "Red"
        }
    }

    # Add an Absatz if the parameter is True
    if($Absatz) {
        [string] $strLogFileAbsatz = "`r`n"
    }

    #Format the text output
    $LogText = "{0,-20} - {1,-7} - {2,0}" -f "$strLogdate", "$LogStatus", "$LogText $strLogFileAbsatz"

    # Write output to powershell console
    Write-Host $LogText -ForegroundColor $strTextColor

    # Write output to logfile
    Add-Content -Path $strLogfile -Value $LogText -Encoding UTF8

    # Add Logfile to local Eventlog of the operating system 
    if($EventLog) {
        Write-EventLog -LogName 'Windows PowerShell' -Source "Powershell" -EventId 0 -Category 0 -EntryType $LogStatus -Message $LogText
    }

}


#-----------------------------------------------------------[Execution]------------------------------------------------------------

Write-Log -LogText "Das ist ein Test." -LogStatus Info
Write-Log -LogText "Das ist ein Test." -LogStatus Success
Write-Log -LogText "Das ist ein Test." -LogStatus Warning
Write-Log -LogText "Das ist ein Test." -LogStatus Error -Absatz
Write-Log -LogText "Das ist ein Test."
#Write-Log -LogText ""

Quelle: Git Repository

Die Funktion nutze ich nun knapp ein halbes Jahr. Bisher keine Informationen vermissen lassen. Tut was es soll.

Viel Spaß beim Ausprobieren. 🙂

Abonnieren
Benachrichtige mich bei
1 Kommentar
neueste
älteste
Inline Feedbacks
View all comments
Robin
29.06.2020 20:57

Hallo Daniel,

wenn Logs Zentral eingesammelt werden, ist das Windows Eventlog eventuell einen Blick Wert, da es ja Microsoft Standard ist. Für den Fall kann diese Funktion verwendet werden:

https://github.com/geberit/elastic-helpers/blob/master/logging_examples/logging.ps1

Ausgabe als Datei ist auch unterstützt, da auch die Windows Admins, die ich kenne, nicht freiwillig das Eventlog verwenden 😉

Gruß