Keeping tabs on what a script is doing is critical for monitoring and debugging. Monitoring a script can be done in many different ways, but it is usually dependent on how it's being executed. If a script is invoked interactively, meaning directly from the console using techniques such as Write-Verbose, Write-Information or Write-Host, it is useful because each command can display messages on the console as the script runs.

But what if this script is getting invoked by a scheduled task or some other process that doesn't involve a human staring at a screen while it runs? In this case, we'll need to incorporate another level of monitoring. An excellent way to monitor a script that doesn't run interactively is by writing to a log file.

There are a few different ways to write text to a text file in PowerShell, and the approach that's used is completely up to the developer. However, before embarking on creating your own logging function, there are a few things to keep in mind.

  • All log lines need to be structured content. No loosey-goosey text messages strewed about.
  • The time should be recorded for each log entry.
  • A severity is recommended or other "tags" to quickly filter information in the log file later.

Let's see how we can build a PowerShell function to incorporate into any of our scripts. Because this function will need to be available to several different scripts, we're going to create a PS1 script just to store our function. The function's name will be Write-Log.

function Write-Log {
     [CmdletBinding()]
     param()
 
 }

This logging function will write a single log line every time it's called. Each line in the log is going to have two attributes that will change depending on what I'd like to record; message and severity, so I will add those as parameters to our function.

function Write-Log {
 ��� [CmdletBinding()]
 ��� param(
 ������� [Parameter()]
 ������� [ValidateNotNullOrEmpty()]
 ������� [string]$Message,
 
 ������� [Parameter()]
 ������� [ValidateNotNullOrEmpty()]
 ������� [ValidateSet('Information','Warning','Error')]
 ������� [string]$Severity = 'Information'
 ��� )
 
 }

Notice that I've chosen to limit the value of the Severity parameter to three choices. By limiting the options, it ensures that I can rely on this field to always be one of three different severities. Once I've got the parameters built out, I'll use CSV to create a structured log file. This will ensure that I can quickly pull up the log file in a spreadsheet program and look through the data, if necessary.

Notice below that I've also added the time. This isn't a parameter because this will always be the time the function was executed.

function Write-Log {
 �� �[CmdletBinding()]
 ��� param(
 ������� [Parameter()]
 ������� [ValidateNotNullOrEmpty()]
 ������� [string]$Message,
 
 ������� [Parameter()]
 ������� [ValidateNotNullOrEmpty()]
 ������� [ValidateSet('Information','Warning','Error')]
 ������� [string]$Severity = 'Information'
 ��� )
 
 ��� [pscustomobject]@{
 ������� Time = (Get-Date -f g)
 ������� Message = $Message
 ������� Severity = $Severity
 ��� } | Export-Csv -Path "$env:Temp\LogFile.csv" -Append -NoTypeInformation
 }

That's all there is to our Write-Log function. We can now add this to any script we like as long as we dot-source it in first. If the Write-Log.ps1 script was in the same folder as the script we're calling it from; we could dot-source it like $PSScriptRoot\Write-Log.ps1.

Once the script knows about the function, it can then be called as many times as necessary in a script.

$foo = $false
 if ($foo) {
 ��� Write-Log -Message 'Foo was $true' -Severity Information
 } else {
 ��� Write-Log -Message 'Foo was $false' -Severity Error
 }

The information would then get recorded to the log file which would look like this:

$foo = $false
 if ($foo) {
 ��� Write-Log -Message 'Foo was $true' -Severity Information
 } else {
 ��� Write-Log -Message 'Foo was $false' -Severity Error
 }

Join the Jar Tippers on Patreon

It takes a lot of time to write detailed blog posts like this one. In a single-income family, this blog is one way I depend on to keep the lights on. I'd be eternally grateful if you could become a Patreon patron today!

Become a Patron!