“Knowing is not enough; we must apply. Willing is not enough; we must do.” [Johann Wolfgang von Goethe]

Abstract

PowerShell is a Microsoft Windows based object orientated script / programming language. It has its own command line interface.

Normally I would prefer a platform independent language like Python. But within a Windows environment you can do almost anything with PowerShell. And sometimes I just do not like to perform all tasks with Excel / VBA. PowerShell can perform tasks in background mode, at a scheduled time, etc.

A first useful function is in my opinion Write-Log. It offers logging functionality similar to Excel VBA Logging.

Appendix – Write-Log Code

Please read my Disclaimer.

<#
.SYNOPSIS
    Write-Log -Message [string] -Severity EVER|INFO|WARN|FATAL
	
.DESCRIPTION
    This script/function enables logging within PowerShell scripts.

    Global variables which control features of this script are:
    [string]$global:LogFilePath    - The text file into which all messages are getting written
    [string]$global:SubName        - The name of the script calling this Log script
    [int]$global:LogLevel          - The log levels:
									 1 logs everything,
									 2 omits INFOs,
                                     3 omits INFOs and WARNings,
									 4 only logs severity EVER messages
    [bool]$global:WriteToHost      - $FALSE = Only write into logfile; $TRUE = Also write to Host
  
.OUTPUTS
	Write-Log writes into a logfile with name [string]$global:LogFilePath.
	if the user has not given this, the standard filename "$PSScriptRoot\Logs\LogFile.txt" is used.
    The contents of a log file will look like:
    INFO: BERND-PC\Bernd 2020-02-16 12:19:36 [zip_and_copy.ps1] - Log started
    INFO: BERND-PC\Bernd 2020-02-16 12:19:36 [zip_and_copy.ps1] - Log finished
	
	In case the user has set [bool]$global:WriteToHost to $TRUE, Write-Log also repeats all log
	messages on screen (Host).

.PARAMETER Message
    The message you want to log.

.PARAMETER Severity
    The severity of the message. This can be 'INFO', 'WARN', 'FATAL', or 'EVER'.
    If global variable LogLevel is 1 then messages with all severities will be logged.
    If LogLevel is 2 then INFO messages will not be logged.
    If LogLevel is 3 then INFO and WARN messages will not be logged.
    If LogLevel is 4 then INFO, WARN and FATAL messages will not be logged.

.EXAMPLE
    # Initialize global logging variables and make log script known
    $global:SubName = $MyInvocation.MyCommand.Name
    $global:LogLevel = 1
    $global:LogFilePath = "$PSScriptRoot\Logs\LogFile_" + $SubName + "_" +
        (Get-Date -UFormat "%Y%m%d") + ".txt"
    $global:WriteToHost = $TRUE
    . "$PSScriptRoot\Write-Log.ps1"

.EXAMPLE
    # How to call
    Write-Log -Message 'Log started' -Severity INFO
    If(-Not (Test-path $ArchiveFile)) {Write-Log -Message "$ArchiveFile was not created" -Severity FATAL}

.NOTES
    Source (EN): http://www.sulprobil.de/write-log_en/
    Source (DE): http://www.berndplumhoff.de/write-log_de/
    Version Date        Who                   What
    1.0     16-Feb-2020 Bernd Plumhoff        Initial Version
    1.1     13-Jul-2020 Bernd Plumhoff        EVER instead of ALWAYS, and optional Write-Host
#>

#Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope CurrentUser -Force
#Clear
#Requires -Version 4
Set-StrictMode -Version Latest

function Write-Log {
    [CmdletBinding()]
    param(
        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string]$Message,
        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [ValidateSet('INFO','WARN','FATAL','EVER')]
        [string]$Severity = 'INFO'
    )
    switch ($Severity)
    {
        'INFO'	{ If ([int]$global:LogLevel -gt 1) {Exit} }
        'WARN'	{ If ([int]$global:LogLevel -gt 2) {Exit} }
        'FATAL'	{ If ([int]$global:LogLevel -gt 3) {Exit} }
        'EVER'	{ <# Will always be logged! #> }
    }
    if (-Not (Test-Path -IsValid $global:LogFilePath)) { $global:LogFilePath = "$PSScriptRoot\Logs\LogFile.txt" }
    [string]$Output = $Severity + ": " + [System.Security.Principal.WindowsIdentity]::GetCurrent().Name +
        " " + (Get-Date -UFormat "%Y-%m-%d %T") + " [" + $global:SubName + "] - " + $Message
    Write-Output $Output | Out-File -append $global:LogFilePath
	If (Test-Path variable:global:WriteToHost) {
		If ($global:WriteToHost) { Write-Host $Output }
	}
}