How to create a log file for your PowerShell scripts

I am a great fan of the KISS method, while KISS stands for Keep It Simple Stupid.

Fortunately, there are two built-in cmdlets in PowerShell to make it easy to create log files: Start-Transcript and Stop-Transcript.

However, keep in mind that you must use a maximum of your script content with the Verbose parameter.
Furthermore, you can also use the Write-Output cmdlet to write your personal messages to the log file.
Otherwise, your log file will just be empty, or only contain error messages…

You must also think about where you want to store your log file(s) and how many of them you want to keep.

Here are three use cases

Unique log file

You want only one log file which is overwritten each time the script is executed.

In the case of one log file, my preference is to keep it in the same folder as the script. Thus you immediately see the script and the log together

I use an automatic variable named MyInvocation to find the path to my running script and replace the .ps1
extension with the .log extension via the Replace method and a regular expression to build the path to the log file.

$Logfile = $MyInvocation.MyCommand.Path -replace '\.ps1$', '.log'

Start-Transcript -Path $Logfile

#Doing some stuff with the Verbose parameter

Get-ChildItem -Verbose

Get-Service -Verbose

Get-Process -Verbose

Write-Output 'Writing some text to the log file'

Stop-Transcript

Two log files

You want two log files: the last run and the run before.

In the case of two log files, my preference is to keep them in the same folder as the script. If you have a folder with several scripts and two log files for each script, it is still readable and clear.

First I remove the old log file, then I rename the current one to .old and finally, I can create a new one named .log

$OldLogfile = $MyInvocation.MyCommand.Path -replace '\.ps1$', '.log.old'

$NewLogfile = $MyInvocation.MyCommand.Path -replace '\.ps1$', '.log'

#Removing the .log.old file

If(Test-Path -Path $OldLogfile) {Remove-Item -Path $OldLogfile}

#Renaming the .log to .log.old

If(Test-Path -Path $NewLogfile) {Rename-Item -Path $NewLogfile -NewName $OldLogfile}

#Starting with a fresh .log file

Start-Transcript -Path $NewLogfile

#Doing some stuff with the Verbose parameter

Get-ChildItem -Verbose

Get-Service -Verbose

Get-Process -Verbose

Write-Output 'Writing some text to the log file'

Stop-Transcript

Multiple log files

You want a longer history than only the last run and the former one.

In this case, my preference is to keep them in a subfolder named Logs or whatever you want.

However, you must also keep in mind that you will have plenty of logs and that you must think to a way for removing unnecessary history.

And in this case, the beginning of the script will be a bit more complicated…

Without explaining every detail, here is what it does

  • Every log file has a time stamp to make it unique in the folder
  • Every time the script runs it keeps only the latest log files and removes the older ones
$CurrentPath = Split-Path -Path $MyInvocation.MyCommand.Path -Parent

$LogPath = Join-Path -Path $CurrentPath -ChildPath 'Logs'

$LogRootName = (Split-Path -Path $MyInvocation.MyCommand.Path -Leaf) -replace '\.ps1
</pre>
</div>
<h2>More about</h2>
<a href="https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_automatic_variables">About
Automatic variables (Microsoft Docs)</a>

<a href="https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.host/start-transcript">Start-Transcript
(Microsoft Docs)</a>

, ''

$TimeStamp = Get-Date -Format yyyyMMdd_HHmmss

$LogFileName = '{0}_{1}.log' -f $LogRootName, $TimeStamp

$LogFile = Join-Path -Path $LogPath -ChildPath $LogFileName

#Change this value to how many log files you want to keep
$NumberOfLogsToKeep = 10

If(Test-Path -Path $LogPath){
#Make some cleanup and keep only the most recent ones
$Filter = '{0}_????????_??????.log' -f (Join-Path -Path $LogPath -ChildPath $LogRootName)

Get-ChildItem -Path $Filter |
Sort-Object -Property LastWriteTime -Descending |
Select-Object -Skip $NumberOfLogsToKeep |
Remove-Item -Verbose
}
Else{
#No logs to clean but create the Logs folder
New-Item -Path $LogPath -ItemType Directory -Verbose
}

Start-Transcript -Path $Logfile

#Doing some stuff with the Verbose parameter
Get-ChildItem -Verbose

Get-Service -Verbose

Get-Process -Verbose

Write-Output 'Writing some text to the log file'

Stop-Transcript

More about

About
Automatic variables (Microsoft Docs)

Start-Transcript
(Microsoft Docs)

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s