As I'm sure you’re now well aware of, the AWS® outage, earlier this month, was caused by simple human error, where an unfortunate soul ran a command without fully understanding its consequences. As sqlrockstar pointed out in his post on the topic Lessons Learned From the AWS Outage, PowerShell's creator, Jeffrey Snover, actually built such functionality to help mitigate such errors into PowerShell itself. So, I thought it would be a good opportunity to look at that functionality in a more detailed, practical manner. In particular, I want to look at using -Whatif and -Confirm within functions.

 

To examine the topic further, I've added a real-world example—in this case, the "Remove-OrionNode" function from the PowerOrion module.

Import-Module-Name"C:\projects\OrionSDK\Samples\PowerShell\PowerOrion\PowerOrion.psm1"-Force
$swis = Connect-Swis 192.168.100.2 -UserName admin -password ''
Remove-OrionNode -SwisConnection $swis -IPAddress '192.168.100.2' -WhatIf


 What if: Performing the operation "Removing Object" on target "swis://192.168.100.2/Orion/Orion.Nodes/NodeID=1"

 

If I called the above three lines, but without the "-whatif" parameter in the final line, the code would simply execute, and the node referenced by "NodeID=1" would be deleted. But as that particular object wasn't actually targeted within the function call—rather, the IP "192.168.0.2" is—is that the node the user expected, or was a different node expected? By simply adding the -whatif parameter, the user can now have a very good understanding of what will happen before a major change is affected.

 

Similarly, if we want to confirm such a change, we can utilise the "-confirm" parameter, providing the user a safeguard, to confirm/reject such changes.

 

Confirm Remove Node.png

 

How to Implement

 

Fortunately, PowerShell provides an excellent framework to allow such expanded functionality. By adding the "CmdletBinding" attribute to your advanced functions, your PowerShell can now behave like compiled cmdlets. Without any other parameters, this is enough to allow passing "-verbose" and "-debug" to your functions. In particular, the "SupportsShouldProcess" allows the -WhatIf and -Confirm functionality we are looking to achieve.

 

For more information on the topic you can run the following command:

 

get-help about_Functions_CmdletBindingAttribute

 

 

However, for a more practical inspection, we will analyze the function below. To enable the functionality, we simply place it just after the function name is defined:

 

[CmdletBinding(SupportsShouldProcess=$True)]
function Remove-OrionNode
  {

    ...
}

 

However, we then call the code by wrapping actual code that makes the edits in an "if" statement, which calls " $PSCmdlet.ShouldProcess("$uri","Removing Object")". So that is the actual logic that calculates what object is under scope, as well as provides the textoutput, which can be seen in the previous screenshot.

 

Conclusion

By leveraging PowerShell's native safeguard functions, you can now easily add a level of robustness, helping to prevent unintended consequences when running your scripts. I'd be interested to hear if you were already doing something similar in your script. If you have any interesting input on the topic, please share in the comments below.