PowerShell Modules – Why bother?
Ever since PowerShell hit the stage it’s adoption has been increasing dramatically – Finally that Windows-based scripting language that not only appeals to Windows administrators with an easy to use structure but has been widely adopted by the industry surrounding the third-party applications. There aren’t many mainstream products out today that don’t support PowerShell. Don’t get me wrong – adoption is great, but with that needs to come a little organization – we, as administrators have managed to spread those PS1 files all over the place – they are scattered on servers here and there, our PC’s, inside of cloud storage. Basically, when we have discovered issues or needed to apply configuration changes we have created our scripts and just left those files laying around. When the time comes to fix that problem again we sometimes find ourselves hunting down those scripts – which, by taking more time than it needs to, sort of defeats the purpose of the efficiency of automation in the first place.
Simply put we need to find a way to take all those scripts that we plan on using over and over and organize them in a way that makes them easy to find and easy to use – this is where PowerShell Modules come into play.
What’s a PowerShell Module
A PowerShell module in its basic is simply a group of functions, where-as each function performs a different task, and represents a new cmdlet. In fact, if you have already created a script that contains multiple functions for organization then you are well on your way to creating a PowerShell module. We can import many modules today from a wide variety of vendors; take for instance VMware PowerCLI module – this is basically a group of functions that perform basic, reusable tasks within vSphere; things like controlling a VMs power, creating a datastore, etc. are all just individual functions within their module, exported as cmdlets.
Within PowerShell we can create modules in 4 different ways – each having their own benefits and drawbacks
- Script Modules – This is perhaps the easiest way to create a module. Essentially, if you already have a PS1 file that contains functions you can simply change your file extension to .psm1, add a command at the end of the file to export certain functions and place the file in a valid module location. Though very easy to create script modules are stored in plain text which could be a security risk in some environments
- Binary Modules – Binary modules are c# code compiled into a .dll file with the .NET Framework. Compiling our modules through .net allows us to leverage a lot more functionality with much more ease. For example, applying multithreading to our cmdlets is much easier when done within Visual Studio than it is to code in straight up PowerShell – which normally results in our cmdlets responding in a timelier fashion than that of script modules.
- Manifest Modules – A manifest module is basically the equivalent of a script or binary module, however is accompanied by a manifest file (.psd1). A manifest file is just a text file containing data which describes how the module it accompanies is processed. Items such as versioning, prerequisites, and updateable help are all contained within the module manifest.
- Dynamic Modules – Dynamic modules are like that of script modules however they are not saved or loaded from persistent storage. Instead, we specify the New-Module cmdlet within our scripts to dynamically load our module in memory – at the end of the script our module will cease to exist.
To script or to module
Future use of the script or code
If when writing my PowerShell scripts, I foresee that I might have to utilize the same script again in the future then I will most likely focus my attentions on creating a script module. By doing we will shave off quite a bit of time when the day comes we need to go looking for the code again as we can utilize built-in PowerShell cmdlets such as Find-Module and Get-Commands to help filter out and search for the functionality we need. Another big advantage to creating a module if you plan on using the script again is consistency – by creating the module and only updating in one spot we can get a consistent outcome, be it good or bad, every single time we run our cmdlets. A good example of this would be retrieving a list of products from a database. If you find yourself writing the same code over and over that retrieves a list of products stored in a table, it might make sense to take this portion of your code and add it to a PowerShell module and export it as a cmdlet. In the end, we would be able to re-use this code with one single line of text (IE Get-Product) rather than writing the code to connect to SQL and run the query each time.
Can my code be “tweaked” to be applied to other entities?
This scenario is one of the most common where I find myself creating modules. It’s not too often where I’m writing a script to manage a specific piece of functionality of an individual object– normally, I’m scripting against an instance of a specific object – but that object itself is part of an entity. A good example of this would be writing a script to defragment my products table in a database. Rather than write a script that does exactly that to just the products table (IE ./DefragProductsTable.ps1), it’s better to write a function that simply takes a table name as a parameter. This way, I could export my function as a cmdlet and essentially use it on any table (IE. Defrag-Table –TableName Products) rather than limiting myself to just one table.
Do I plan on sharing this script?
Whether you share your script between servers within your organization or with the greater community online it’s always a good idea to do so by means of a module. Why? For starters, it makes generating help content a lot easier as well as the ability for any user consuming your code to update that help documentation (Manifest Modules allow us to specify a Help file URL which we can manage). Also, versioning – by versioning our modules we are in better control of releasing updates or enhancements into any infrastructure. Thirdly, a module is more location/organization agnostic than a script. Thinking back to our previous example – sharing a script that defrags a specific table within a specific database will require anyone consuming to either make changes to the script or have the exact same environment setup as yourself – I think we can agree that the latter is farfetched. That said, the module, which basically contains a generic defrag cmdlet is essentially environment-agnostic depending on how it is written. And finally comes prerequisites. How often have you written a script which has worked perfectly on one system and then copied it to another only to have it fail. I’ve done this plenty – and mostly it fails because I’m missing some package or another module on the new server. A manifest module will allow us to define just what other modules our module requires – and we can set it up to automatically load and unload these modules at the same time ours is invoked.
So, with all this I hope you have a little stronger understanding of modules and maybe the urge to start using them. Honestly, if you aren’t using modules today you are not “doing it wrong” – however, you would have to search deep to find a script that you won’t find any code or functions that would be a good fit to live inside a module. As with most anything in IT if you have done it once you will most likely be doing it again – so save yourself some time, effort, and stress by packing up your PowerShell code in a module – you won’t regret it.
- 5 tips to help you explore the world of PowerShell scripting
- Deploy Hyper-V VM Switches and vNIC consistency with PowerShell