When you create scripts for people who only know how to run scripts they have been instructed to, those regular error messages in PowerShell are very scary and confusing.
Case in point, try to run Do-Something and you receive following error:
Do-Something : The term 'Do-Something' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At line:1 char:1 + do-something + ~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (do-something:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException
That’s not going to work, it scares and confuses people. Everything starting from “At line” is unnecessary noise which is not helpful in the least. These people are going to only see large batch of red noise and have very difficult time finding the actual, useful error message from it.
PowerShell should have the option to display more concise error messages, like so:
Do-Something : The term ‘Do-Something’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
That’s all you need for an error, all the extra noise still remains accessible through $Error variable.
So I had to create a function that captures errors and displays concise error message as to avoid unnecessary panic and confusion, which is pasted further below. Unfortunately it takes quite a bit of effort to hide standard error messages. You can either use $ErrorActionPreference = ‘SilentlyContinue’, which then proceeds to hide all errors, which may not be what you want. Or you can use -ErrorAction ‘SilentlyContinue’ parameter. That however does not catch terminating errors, so you also need to wrap the command inside Try { }.
Finally the function needs to be wrapped inside If (-not $?) {Get-ErrorMessage} because by default Catch {} catches only terminating errors. In my experience changing all errors to be terminating errors is just painful, so I never do that. This is probably the most annoying thing I have to do to make my scripts work for people who really only know what they’ve been instructed.
I would even like to use parameter validation more, but even those output so much noise that it simply scares people. I always end up handling parameter validation inside the script so that I can output concise errors that do not scare people. There are plenty of other examples, but I think you all get my point by now.
This is a lot of work, but I don’t really see any other way to accomplish this. Do you?
I know there is also CategoryViews for error messages, but they’re not really suitable for the target audience either.
Function Get-ErrorMessage { [CmdletBinding()] param ( [Parameter(Position = 0, ValueFromPipeline = $true)] [System.Management.Automation.ErrorRecord]$ErrorRecord ) If (-not $local:ErrorRecord) { [System.Management.Automation.ErrorRecord]$ErrorRecord = $global:Error[0] } If ((($ErrorRecord.Exception | Get-Member -MemberType 'Property' | Select-Object -ExpandProperty Name) -contains 'InnerException') -and ($ErrorRecord.Exception.InnerException)) { Write-Output $ErrorRecord.Exception.InnerException.Message } Else { Write-Output $ErrorRecord.Exception.Message } }