Reusable Code for Logging in Your Scripts
Anyone who’s been on my site or seen other articles I’ve written would know that I use PowerShell heavily. PowerShell is one of the most important tools in any administrators arsenal. When it comes to scripting to help automate tasks in your environment, it’s unbeliveable powerfull. PowerShell can be used for quick one or two line cmdlets or can be used as the basis for some pretty impressive tools.
While PowerShell is targeted at administrators rather than professional developers, it’s common that we miss out on some best practices in writing code – after all, we’re generally just trying to get a task done quicker, not building large production applications.
Even so, good practices can help take a PowerShell script to the next level. One of these practices is building in logging. I’m as guilty as anyone of letting my “logging” in scripts take the form of a bunch of write-host cmdlets, writing content to the screen while I sit watching my code run, waiting to stop the code if I see an error.
For many of my scripts now though, I’ve build a simple and effective function which I can reuse to write a log file while the script runs. In this article, I’ll show you that function and how I use it.
What is a Function?
You can think of a function in PowerShell as a reusable block of code that you call upon as needed. For example, let’s say we want to perform some calculations based on two numbers provided by the user at several points in our script. Well if we did this all inside a script, we would end up typing the same thing over and over again every time we wanted to perform that calculation. That would look something like this:
##Script to calculate the area three triangles
[int]$Triangle1Base = read-host "Enter the width of triangle 1"
[int]$Triangle1Height = read-host "Enter the height triangle 1"
##Multiply height times base divided by two
$triangle1Area = ($Triangle1Base * $Triangle1Height) / 2
Write-host "The area of Triangle 1 is $triangle1area" -ForegroundColor Green
[int]$Triangle2Base = read-host "Enter the width of triangle 2"
[int]$Triangle2Height = read-host "Enter the height triangle 2"
##Multiply height times base divided by two
$triangle2Area = ($Triangle2Base * $Triangle2Height) / 2
Write-host "The area of Triangle 2 is $triangle2area" -ForegroundColor Green
##Script to calculate the area three triangles
[int]$Triangle3Base = read-host "Enter the width of triangle 3"
[int]$Triangle3Height = read-host "Enter the height triangle 3"
##Multiply height times base divided by two
$triangle3Area = ($Triangle3Base * $Triangle3Height) / 2
Write-host "The area of Triangle 3 is $triangle3area" -ForegroundColor Green
The output of this script is that we read in the base and height of the triangle and then output the area, as shown in Figure 1.

This is a simple example but as you can probably see, the script does the same calculation three times. If we were to use a function, and pass in our parameters then this becomes a much cleaner script:
Function CalculateTriangleArea{
param(
[Parameter(Mandatory = $true)]
[string]$triangleName
)
[int]$base = read-host "Enter the width of triangle $triangleName"
[int]$height = read-host "Enter the height triangle triangleName"
$area = ($base * $height) / 2
Write-host "The area of Triangle $triangleName is $area" -ForegroundColor Green
}
CalculateTriangleArea -TriangleName "1"
CalculateTriangleArea -TriangleName "2"
CalculateTriangleArea -TriangleName "3"
In this script we use a function to hold all the reusable code and simply call it three times with a different triangle name each time. The output is the same (Shown in Figure 2).

By putting our reusable code into the function, we’ve made our script more efficient. We can now call the CalculateTriangleArea function as many times as we want with just one line of code for each.
Creating a Log Function
Taking this further, when we think of logging, there are some key things we want to do for each line we add to a log file. We want the date / time the event happened and we probably want to add a log type (Info, Warning, Error) to each line so we can debug quicker.
The function I use for logging has the following parameters:
- Message – The content of the message to be posted to the log
- LogFilePath – The path to the log file to write to
- LogType – The type of log entry (for example, Info, Warning, Error)
- DebugEnabled – If this parameter is provided, the log output will also be written to the screen
##Function to write log file##
Function Write-Log {
param(
[Parameter(Mandatory = $true)]
[String]$Message,
[Parameter(Mandatory = $true)]
[String]$LogFilePath,
[Parameter(Mandatory = $true)]
[String]$LogType,
[Parameter(Mandatory = $false)]
[switch]$DebugEnabled = $false
)
$Date = Get-Date
$Message = "$Date - [$LogType] $Message"
Add-Content -Path $LogFilePath -Value $Message
if ($DebugEnabled) {
If ($LogType -eq "Error") {
write-host $Message -ForegroundColor Red
}
elseif ($LogType -eq "Warning") {
write-host $Message -ForegroundColor Yellow
}
else {
write-host $Message
}
}
}
With this function in your script, adding to the log file looks like this:
Write-Log -Message “<Message to be posted> -LogFilePath “<Path to your log file>” -LogType “Info” -DebugEnabled
If DebugEnabled is specified then the output is written to the screen and any logs with the log type “warning” will be written in yellow and “error” will be written in red.
Adding the Function to your Script
You can add the function to your script in two ways. The first way is to simple add the code to the top of your script similar to my first example above. If you have a more complex script you might want to store it in a separate file. In this case you can save it as it’s own file and use dot sourcing at the start of your script. This would look like this:
.\YourLogFunctionFile.ps1
If you source like this, the script will behave as if you have the code directly in the script.
Summary
Adding logging to your scripts is a great way to level up your code and provide granular information about how the script runs. Adding this as a function means you don’t need to handle everything for logging each time you want to write to the log file. Hopefully this reusable function comes in useful!
