How PowerShell Modularization Can Get You Out of Script Hell


Crista Perlton

Crista Perlton


Why You Should Create a Package Approval Workflow for  27th September, 2023

Do I really need to leave .NET Framework for .NET 8? 13th September, 2023


How PowerShell Modularization Can Get You Out of Script Hell

Posted on .

Script Hell. That tangled wasteland of unorganized, I-swear-I’ve-written-this-15-times-already PowerShell scripts. No one wants to be in script hell. The best time to get your team out of script hell was yesterday; the second-best time is now. Using PowerShell modules is an effective way of freeing yourself from script hell. However, without proper planning, you may find yourself in a deeper circle of PowerShell Hell: module hell.

This article gives you the basics of PowerShell modularization and how to avoid PowerShell hellishness. Conquering modularization will help your team level up its PowerShell use.

Script Hell

Script Hell is a place where anarchy rules. Where people create personal scripts for company use, build information silos, and don’t document changes applied to edited scripts. Really, script hell is just a description of bad scripting practices. Do you have long, unwieldy, and brittle scripts that are difficult to maintain? Or maybe a lot of copy/pasted code that does mostly the same thing? Most teams end up there without even knowing how it happened.

The thing about script hell is the longer you stay, the more brittle and more unmanageable your scripts get. This becomes a BIG problem as your team starts to move faster and you need to scale.

What is modularization and how does it help with Script Hell?

Modularization describes the practice of taking a large thing and breaking it down into smaller, more manageable things. For example, a screenplay could be modularized into scenes, acts, and lines making it easy for actors to refer to a specific part of the play. I modularize my yarn collection into different bags, sorted by color. PowerShell scripts are modularized through cmdlets, functions, and PowerShell modules. Let’s break down these three components.

Cmdlets are the basic building blocks of any PowerShell script used to automate and simplify routine administration tasks across local and remote Windows-based systems. While cmdlets are used in PowerShell script files, they can also be typed into the PowerShell command prompt directly to carry out simple commands like “show me files” or “run programs.”

Most members of your team know the most common cmdlets and know how to use them. However, creating custom cmdlets requires an incredible amount of experience and may be beyond the skill of even your highest-level team members.

Functions are used to create code in small “blocks” to reduce the redundancy of the repeated code. Instead of copy/pasting the same code repeatedly, create a PowerShell function. Functions are code collected to perform something one or many different times. Give the function a name and re-use it multiple times by using the name instead of writing out all the code. For example, the following function called “Get-Version” returns the version of PowerShell installed on your system.


function Get-Version {




Major Minor Build Revision

----- ----- ----- --------

5     1     14393 693

You probably already use these. Most PowerShell users are familiar with script-level functions and use them in their own scripts. Then there are module-level functions. Module-level functions are shared and used across different scripts. It’s important to consider what script-level and module-level functions your teams are (and will be) using before diving in and creating custom PowerShell modules. It’s super easy to get carried away and you may quickly find yourself in module hell, surrounded by confusing modules that will never be used.

PowerShell modules (.psm1 files) allow you to combine like scripts into a single, cohesive package that can be easily shared with other users. Users can import your modules/packages into their PowerShell environment to add functionality. Modules aren’t directly run in the PowerShell; instead, they become a part of it. For example, the Azure module allows PowerShell to manage Microsoft Azure service. Think of it like installing a new Wi-Fi adapter in a computer: As soon as the adapter is installed, the computer will have Wi-Fi functionality added.

Your team is most certainly using PowerShell modules. is an amazing resource to find PowerShell modules that are conveniently wired into PowerShell. You may even be making your own modules already. Creating a custom module doesn’t require as much XP as creating custom cmdlets but should still only be handled by higher XP team members since it requires at least 10,000XP.

How (and Why) to Make Better Modules

Creating Modules

Creating a module is in theory super easy. It only requires you to save a PowerShell script file as a .psm1. You can then publish it to the PowerShell Gallery or a private server like ProGet. But, doing JUST this will lead you to a place even worse than Script Hell: Module Hell. Simply renaming your notepad .txt file to .psm1 would be like converting a Batch script to a PowerShell one by changing the ending from .cmd or .bat to .ps1. In many cases, it works…but not all.

Challenges & Solutions to USING Modules

PowerShell modules are great… in theory. Your team can easily reuse existing code. However, just using modules puts you on the border of module hell. The key is to treat your modules like other documents and scripts: be organized. Start by creating a top folder that makes sense for your team and use version control as you go.

Versioning and Updating

Since PowerShell modules become a part of the PowerShell, they become dependencies for anyone working with them. That means that poor update management plans could lead to catastrophic failures.

Many of the modules that teams use are third-party found on PowerShell Gallery. That’s great and convenient! But, third-party modules require license verification and quality and vulnerability checks. Using third-party modules saves a lot of time, but of course, it also adds one more opportunity for risk to come into your PowerShell use, whether from licenses you’d rather avoid or from some vulnerabilities you didn’t realize are in there. Private package repositories like ProGet can help you with automating these processes.

Challenges & Solutions to CREATING Modules

Your team can share your first-party code, so others don’t reinvent the wheel. Since these modules are made in-house, you don’t need to worry about the issues you’d have with third-party modules, but you do need a place to host these first-party ones.

Remember, PowerShell modules become a part of PowerShell. This makes it essential for everyone to be working in the same environment. Updates heavily affect what your team is working on. Ignore this and risk entering module hell.

An excellent solution to combat this is having a central, regulated repository that your team can pull from. Obviously, my preferred repository is ProGet. Managers control what packages are in the repository and update them when they need to. With everyone pulling the same modules, everyone is guaranteed to be working on the same PowerShell (instead of four different people all working with four different modules).

Modularization Challenges and How to Tackle Them

Time FrameChallenge(s)Advice
Short-termAdoption Costs– Plan what you will turn into a PowerShell module- Plan who will create PowerShell modules
Mid-termMaintenance– Create and adapt your maintenance plan- Adopt version control, source control, and change control
Long-termUndocumented Processes– Slowwww dowwwwwwn- Actually follow your plan- Document everything

Short-term Problems and Solutions

The first and most obvious challenge to learning anything new is the training time and costs. (You don’t even wanna know how long it took me to get to the knitting XP I’m at now. Lots of knots.) Learning new things takes time. PowerShell modules are no exception.

An essential step to short-term PowerShell modularization is planning. As I’ve said before, creating modules without a plan will almost certainly lead to module hell. A good place to start your plan is at your frequently copy/pasted, script-level functions (if they keep being used over and over and over, it’s prudent to make them into a PowerShell module). Keep in mind: a good-quality script function is infinitely better than a subpar module. There’s no formula for the perfect module ratio, but be aware that too few modules and too many modules are both forms of module hell.

Another short-term step is deciding what you should modularize. Creating modules is easy. The hard part is knowing WHAT to modularize. This actually takes more PowerShell XP than you might realize. The person deciding what to modularize needs strong institutional knowledge (and it’s okay if that person ISN’T you). There’s no modularization formula. Keep in mind the purpose of modularization: you’re modularizing to make it easier for you and especially for others (with possibly less PowerShell XP) to write PowerShell.

Mid-term Problems and Solutions

Okay, now the new flock of modules has been created. The chief mid-term problem is their update and maintenance. Who is responsible for them? Chances are it’s going to be the same person who made the modules who will be responsible for their upkeep, but it doesn’t HAVE to be. Assessing if that person actually has the time to maintain modules that they wrote is an important part of (you guessed it) your planning.

The most important step mid-term is to create a change and maintenance plan. It’s easy to create a module, but how do you change it when you need to? You have to be able to answer this question with more than ¯\_(ツ)_/¯.

To make such a plan, you need a team with these leveled-up skills:

Module Versioning
Create a new version of a file when you make changes with a new version number. Version numbers communicate what changes mean (Semantic Versioning). Changes made at-will lead to a discrepancy between PowerShell environments (a BIG problem).

Source Control
Once you publish the module, you never want to wonder where is the original code (the .psm1 file) is. Commonly accepted best practice is to use source control to manage your modules and to NOT download a module, edit it, change its version number, and republish it.

Change Control
Finally, you need to have a clear outline of who is responsible for changes and how are they going to update the modules. Change control is a time investment, but it’s worth it because you save sooo many headaches.

Long-term Problems and Solutions

At this point, modules are created and controls are in place. The chief long-term problem is a lack of documentation. Documentation (and of course a plan for it!) is one of the two top concerns for long-term module maintenance. I said it before and but it’s worth mentioning again: it’s super easy to get carried away and create too many modules. Doing this will quickly lead you down the path to module hell because you’ll probably be so caught up in creating cool new modules that you aren’t documenting them. It’s imperative to document changes you make to modules, especially if you’re not the only one maintaining them.

The second top concern at this stage is to think like your software developer colleagues by thinking of this maintenance process in terms of a Software Development Lifecycle (SDLC). Establishing an SDLC that includes versioning, source control, change control, testing, and eventually even retiring the module. will discipline your module processes AND you can automate them.

Be Wise When You Modularize

PowerShell modules are incredibly powerful and can help you and your team climb out of script hell. The threat of falling into module hell is very real but easily avoidable by learning to think like a developer (for a short time) and creating plans and policies for taking care of your modules.

Start leveraging modularization immediately to get your team’s PowerShell level up. Just keep in mind that while Script Hell is bad… Module Hell is worse.

Crista Perlton

Crista Perlton