Recently I have been writing some very long PowerShell scripts for many different purposes but I ran into a common problem… How to deal with error handling.
There are many options available and the Windows PowerShell inbuilt -OnError function works fine, but I wanted something more, and more to the point, the customer wanted more. With this in mind I decided that the best option was going to be to export to a log file in a format that was readable with the CMTrace tool that comes packaged with SCCM.
Using this method means that I can output all information, including success and failures for each task that I run. It also means that as the script is running, users can monitor the progress in real-time.
The first thing you need to do is place the following variables somewhere at the top of your script
$CurrentUser = [Environment]::UserName
$StartDateTime = Get-Date -Format “HHmmss”
$TZbias = (Get-WmiObject -Query “Select Bias from Win32_TimeZone”).bias
$Component = “Application Export”
$LogFile = “C:\Logs\My Script.Log”
$CurrentUser will get the currently logged on username to use for the “File” column. This is not required but could (and usually is) set to the currently running script by way of the following line. I have chosen this method because my output file is the same as the script name making this useless, and many people will be logged on to the same server running the same script so i would like to be able to identify which user is running the script
$CurrentFile = $MyInvocation.MyCommand.Name
$StartDateTime fetches the current date and time as of the script launch time, this is going to be used for the “Thread” column. This is not required and is a personal choice. You could put many other things here, like the current username, script name, or just about anything else you want.
$TZbias gets the current timezone. This is required for the “Time” column. Without this the time will not be recognized and the log will not be in the correct format for CMTrace.exe.
$Component can be defined to anything you cant. I have it set to the current script. Have a play around with some of these variables and see what you get as the output
##Output to Log
$Time = Get-Date -Format “HH:mm:ss.fff”
$Date = Get-Date -Format “MM-dd-yyyy”
$Type = “1”
$LogText = “+++Starting new thread+++”
$LogOutput = “<![LOG[$($LogText)]LOG]!><time=`”$($Time)+$($TZBias)`” date=`”$($Date)`” component=`”$($Component)`” context=`”$($Context)`” type=`”$($Type)`” thread=`”$($StartDateTime)`” file=`”$($CurrentUser)`”>”
Out-File -InputObject $LogOutput -Append -NoClobber -Encoding Default –FilePath “$LogLocation$LogFileName”
Each time you would like to output a line to the log you will need to paste the whole text above. Let’s go through now and break it down to see what is going on
$Time = Get-Date -Format “HH:mm:ss.fff”
$Date = Get-Date -Format “MM-dd-yyyy”
Both of these fetch the date or the time and bind it to a variable. This will need to be set each time to ensure that the time stamp for your log matches the time of the task running
$Type = “1”
This line will define the formatting of the line. “1” means information and will be a plain line with a white background. “2” means warning and will have a yellow background. “3” means error and will have a red background so set accordingly
$LogText = “+++Starting new thread+++”
This is the main meat of the script. This is where you can put all of your information about what is going on. I will always start and finish a script with a clear maker such as this. Setting this as a variable and not putting it directly into the next line means that you ave more flexibility to change it, something like the following line
$LogText = “The following function has failed:” + $Function
This variable can also be set to a function (such as Get-Item) and will correctly display multiple lines in CMTrace
$LogOutput = “<![LOG[$($LogText)]LOG]!><time=`”$($Time)+$($TZBias)`” date=`”$($Date)`” component=`”$($Component)`” context=`”$($Context)`” type=`”$($Type)`” thread=`”$($StartDateTime)`” file=`”$($CurrentUser)`”>”
This is something that you should not need to alter. All of the data here that you could possibly want to modify is defined as variables. Just in case it is not clear, this is a single line. WordPress has limitations
Out-File -InputObject $LogOutput -Append -NoClobber -Encoding Default –FilePath “$LogFile”
This is where we output all of our hard work to a file. The “Append” function will place all text at the end of the file. “NoClobber” prevents the script from overwriting the log file with a new one each time you run this command
If you have any questions feel free to write something in the comments below
this is great! very exciting stuff. do you have a sample script that I can fully analyze for use?