Something that I've been thinking about recently, and I'd like some input from the good people of Stack Overflow on.
I run a fairly large number of PowerShell scripts on differing schedules (using Task Scheduler). These scripts generally gather data and store it in SQL tables for me. I would say I am running 40-50 scripts or so at the moment, maybe more.
One thing that I have seriously been considering recently is the best way of:
This is going to be a fair bit of work to do, so I'd like to go in with the right approach from the start.
The only way I can see of achieving something like this would be to do the following:
Set $ErrorActionPreference to "Stop"
This should cause any exceptions to trigger a Try/Catch block.
Run the entire script within a Try/Catch/Finally block.
Finally block is optional of course. Something like this:
$ErrorActionPreference = "Stop"
Try
{
$Content = gc "C:\Temp\NonExistentFile.txt"
foreach ($Line in $Content)
{
Write-Host $Line
}
}
Catch
{
Write-Host $_ -ForegroundColor "Red" -BackgroundColor "Black"
break
}
Log the "Transcript" Data into HTML and email the content on failure.
I've tried a few ways of logging, and one of the keys things for me is that I want something that is:
I started out writing text into .txt files, but it was a bit of work to do.
Start-Transcript was OK, but did not include the date/time on each line.
I had some success with a custom Function that would use Start-Transcript, and would write any text I sent into it into Write-Host, with the date/time at the start of each line.
But ultimately I think what I need to do is log into a .html document, and then email the contents of this if an error occurs. Something like this as an example:
Function Send-ErrorEmail
{
Write-Host "Would Send Email Here" -ForegroundColor "Magenta"
}
Function Write-Html
{
[CmdletBinding()]
param
(
[Parameter(ValueFromPipeline=$True)]$Text,
$HTMLTag
)
[string]$CurrentDateTime = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss - ")
switch ($HTMLTag)
{
"h1" {$ReturnText = ("<h1>" + $Text + "</h1>")}
"h2" {$ReturnText = ("<h2>" + $Text + "</h2>")}
default {$ReturnText = ("<p>" + $CurrentDateTime + $Text + "</p>")}
}
Write-Host -ForegroundColor "Yellow" ($CurrentDateTime + $Text)
return $ReturnText
}
$ErrorActionPreference = "Stop"
Try
{
#Stores the HTML File
$LogfilePath = "C:\Temp\LogFile.html"
#Begin HTML
$HTML = @()
$HTML += "<html><head></head><body>"
$HTML += "Begin Script" | Write-Html
#Loop through Computers
$Computers = "LocalHost", "DoesNotExist", "127.0.0.1"
foreach ($Computer in $Computers)
{
#Get Services
$HTML += "Computer: $Computer" | Write-Html -HTMLTag "h1"
$Services = Get-Service -Computer $Computer
$HTML += $Services | ConvertTo-Html -Fragment
}
#Complete HTML
$HTML += "Script End" | Write-Html
$HTML += "</body></html>"
$HTML | Out-File $LogfilePath
}
Catch
{
#Add Exception to HTML
$HTML += $_ | Out-String | Write-Html
#Complete HTML
$HTML += "</body></html>"
$HTML | Out-File $LogfilePath
#Send EMail
Send-ErrorEmail
#Exit Script
exit
}
Any thoughts? Improvements you think I could make? Obviously the HTML document is ugly without CSS formatting, and the Send Mail function doesn't do anything, but it seems to be the simplest way to do what I want.
I can of course dot source any functions amongst all of my scripts for ease of changing a notification email address or similar.
The Trap statement can also be used to handle terminating errors in scripts.
The throw keyword causes a terminating error. You can use the throw keyword to stop the processing of a command, function, or script. For example, you can use the throw keyword in the script block of an if statement to respond to a condition or in the catch block of a try - catch - finally statement.
You can interrupt and stop a PowerShell command while it is running by pressing Control-C. A script can be stopped with the command exit. This will also close the PowerShell console.
For global error handling I prefer to use a trap statement.
function ErrorHandler($error)
{
... write out error info
... send email message with error info
... etc
}
trap { ErrorHandler $_; break }
... rest of script code
And if you want to bail on any error, then yes, set $ErrorActionPreference
to Stop
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With