When writing scripts, targeting multiple runtime versions can be really painful, scripts can be forked in different files or contain hairy conditional statements to handle differences/missing between versions of PowerShell runtime/modules, resulting in unreadable and unmaintainable spaghetti code.
What if you instead detect missing commands and supply an implementation for those when needed? This would allow you to have your scripts look the same and basically be agnostic to the which runtime it’s running on, making code more concise and easier to maintain.
The technique for this is called polyfilling and is common practise in web development where things can differ between browser versions and vendors.
It turns out it’s fairly simple to do in PowerShell, I’ll demonstrate this using the Expand-Archive command that was introduced in PowerShell 5, which extracts files from a specified archive
Expand-Archive
-DestinationPath] <String>
-LiteralPath <String>
It’ll obviously fail miserably on previous versions of PowerShell
As PowerShell has the full power of .NET we can utilize the ZipFile class that has been provided since .NET 4.5 (for even older versions of PowerShell we could also potentially just shell out to 7zip or similar command line utility or utilize 3rd party .NET assembly, as we can do anything in our polyfill that’s possible PowerShell). Such a polyfill could look something like below:
if (-not (Get-Command Expand-Archive -ErrorAction SilentlyContinue))
{
& {
Add-Type -AssemblyName System.IO.Compression.FileSystem
function global:Expand-Archive
{
param([string]$Path, [string]$DestinationPath)
[System.IO.Compression.ZipFile]::ExtractToDirectory($Path, $DestinationPath)
}
}
}
The above script checks if command exists, if it doesn’t it’ll execute a code block which will create a globally available function, with the parameters and functionality we expect. To use it in our scripts we dot source it into our script or shell
. .\Expand-Archive.Polyfill.ps1
and it’ll be available for us to utilize just like we would have done in a newer version of PowerShell.
Conclusion
Polyfilling is a very neat way having more homogenous and maintainable scripts, while also letting you adopt new commands and features, even if you have one or two old servers in the closet ;)
This post is licensed under a Creative Commons Attribution 4.0 International License