
close
close
Chance to win $250 in Petri 2023 Audience Survey
In the first article of this short series I laid out the business problem and began the process of creating a PowerShell tool to solve it. My goal is not necessarily to have a finished solution at the end, but rather to teach you along the way and understand the development process. Sometimes learning the thought process is just as important as language and syntax.
The basic script I wrote for the first article works fine as long as nothing goes wrong. But what if one of the computers is offline or I don’t have permission?
With Try/Catch, you use two scriptblocks. In the Try {} block, put in as much PowerShell code that you want to “try” to run. Typically these are commands that might have predictable errors like an offline computer or bad credentials. The corresponding Catch {} block contains the code to run when an error is raised or caught. It is possible to have different Catch blocks for different types of errors, but for now we’ll use one to handle everything. The other important detail that trips up many novice PowerShell scripters is that the error must be terminating.
Without getting too sidetracked into PowerShell errors and exceptions, know that in order for Try/Catch to work, the command in the Try block must create a terminating exception. You can accomplish this by setting the ErrorActionPreference to ‘Stop’. However, you rarely change the preference variable. Instead, use the common parameter -ErrorAction and set the value to ‘Stop’.
Here’s the revised script.
#requires -version 3.0 #TryCatch-HotFixReport.ps1 Param([string[]]$Computername = $env:COMPUTERNAME) foreach ($Computer in $Computername) { Try { Get-Hotfix -ComputerName $Computer -ErrorAction Stop | Select-Object -Property PSComputername,HotFixID,Description,InstalledBy,InstalledOn, @{Name="Online";Expression={$_.Caption}} } #Try Catch { Write-Warning "$($computer.toUpper()) Failed. $($_.exception.Message)" } #Catch } #foreach computer
When an error is caught, the exception object is “caught” by the Catch block. The $_ reference in the Catch block is to the exception object. All I’m doing is displaying the exception message. But now look at the result:
Param( [string[]]$Computername = $env:COMPUTERNAME, [string]$Description, [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty )
This is the way I handle credentials. The script will accept a credential object, or if I enter a name I get the credential prompt. But how do I figure out how to pass these optional parameters? I find the best way is to use a hashtable and splatting.
I think you’ll find the splatting technique very useful. You create a hashtable where the keys match the names of a PowerShell command’s parameters. The beauty of hashtables is that they are easy to change on the fly based on whatever conditions you want to test.
#create a hashtable of parameters to splat to Get-Hotfix $params = @{ ErrorAction = 'Stop' Computername = $Null } if ($Credential.UserName) { #add the credential $params.Add("Credential",$Credential) } if ($Description) { #add the description parameter $params.add("Description",$Description) }
The variable $params is now a hashtable of all the parameters for Get-Hotfix. Notice I set Computername to NULL. This is because I need to set a different value for each computer.
foreach ($Computer in $Computername) { #add the computer name to the parameter hashtable $params.Computername = $Computer
All that remains is to pass the hashtable to the cmdlet. The tricky part is remembering the syntax.
Try { Get-Hotfix @params |
Remember, the variable name is params and the @ symbol instructs PowerShell to splat it to the command.
[ValidateSet("Security Update","HotFix","Update")] [string]$Description,
The ValidateSet() test will verify that the user enters one of the choices.
#requires -version 3.0 #AddFeatures-HotFixReport.ps1 Param( [string[]]$Computername = $env:COMPUTERNAME, [ValidateSet("Security Update","HotFix","Update")] [string]$Description, [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty ) #create a hashtable of parameters to splat to Get-Hotfix $params = @{ ErrorAction = 'Stop' Computername = $Null } if ($Credential.UserName) { #add the credential $params.Add("Credential",$Credential) } if ($Description) { #add the description parameter $params.add("Description",$Description) } foreach ($Computer in $Computername) { #add the computer name to the parameter hashtable $params.Computername = $Computer Try { Get-Hotfix @params | Select-Object -Property PSComputername,HotFixID,Description,InstalledBy,InstalledOn, @{Name="Online";Expression={$_.Caption}} } #Try Catch { Write-Warning "$($computer.toUpper()) Failed. $($_.exception.Message)" } #Catch } #foreach computer
Of course, we’re not done, although this script is certainly usable as is. But there is at least one more feature to implement and there is some polishing to be done to make this a complete PowerShell tool.
More in PowerShell
Most popular on petri