What is a “roll back” you ask? (I know you didn’t really ask, but for those that wanted to ask…) in general terms, it is rolling back to a previous version of some piece of software, in this case a PowerShell module. For example, going from module version 1.2 back to 1.1.
A customer asked me, “What’s the best way to roll back to a specific version of a PowerShell module?“
I said, “As a consultant, the answer is ‘it depends’“, ha ha! Just kidding. Well, kind of kidding. Okay, not really kidding, but all kidding aside… The process usually follows this workflow (assuming this is a public module, which you do not own/maintain):
Reminder: Because this happens so often, it’s like struggling with a USB plug – – – Whenever you are working with installing, updating or removing PowerShell modules, open the PowerShell console using “Run as administrator”. Alternatively, you can manage them under your “user” scope alone.
For the following examples, I’m using the PowerShell module: dbatools. There is nothing wrong (as far as I’ve seen) with the latest version, but I’m going to roll it back to a previous version to demonstrate my incoherent blabbering.
Scenario A – Old Version Still Installed
If the PowerShell module was updated using Update-Module, there’s a good chance that the prior version(s) are still installed on the local system. To confirm, use Get-Module <modulename> -ListAvailable.
In this example, I have two (2) versions installed (1.0.15 and 1.0.20). I want to uninstall the newer version (1.0.20) and leave only 1.0.15 installed.
I would normally use Uninstall-Module <modulename> -RequiredVersion <bad-version> or in this example: Uninstall-Module dbatools -RequiredVersion 1.0.20, as shown below.
You may get an error saying another module is “dependent” upon the one you’re trying to remove (see example above). If so, make note of the dependent module, uninstall it, then try the first uninstall again. Once you have the version you want, you can reinstall the dependent module (assuming it’s not actually dependent on the version you just uninstalled, doh!!)
After all this fuss, it now shows dbatools version 1.0.15 installed.
Scenario B – PS Gallery
If only the newest version (the bad version) is installed, check to see if the prior version is still available on the PowerShell Gallery. You can do this using Find-Module <modulename> -AllVersions.
Warning: dbatools lists pretty much every version since inception, so the list is very long.
If the results show the version you want/need, simply uninstall the current module and install the specific version from the PS Gallery.
Tip: This method supports rolling back to as far back as the author maintains in the PS Gallery. If they chose to unlist a particular version that you need, this won’t work, and you’re on to scenario C below.
Scenario C – GitHub Repository
If the prior version you need is no longer available on the PowerShell Gallery, the next place to look is on the “Project site” or GitHub repository. In some cases, this isn’t possible, but thankfully, it’s more often available than not.
Go to the GitHub site, open the repository, confirm the version, and the branch, and click the Clone or Download button, then click Download Zip. Extract the ZIP file contents somewhere.
Keep in mind that the folder structure provided by the GitHub ZIP download is not the same as what PowerShell modules require in the default path environment. Use the following command to display the current module path…
(Get-Module <name> -ListAvailable).Path
Note the version number in the path string. You will need to “spoof” this to match the version you downloaded so the PowerShell environment will properly recognize it. For this example, just pretend it shows “…\1.0.20\…” and “…\1.0.15\…” doesn’t exist.
Navigate to the parent folder (e.g. the module name itself, “dbatools”), such as “c:\Program Files\WindowsPowerShell\Modules\dbatools”
Create a new sub-folder for the version you want (i.e. “1.0.15”)
Open the ZIP file, drill-down under the first root-level folder, to see the main files and folders. Extract the contents from there into that new module path folder on your hard drive.
IMPORTANT: This extract/copy process will place more than is really needed, but it’s okay. PowerShell will only load what it needs and ignore what it doesn’t need.
If there is not GitHub (or other) repository available, or the version is no longer available for some reason, you’re on to scenario D below.
Scenario D – F**k it
That’s right, just F**K it. Yell out obscenities, and claim you have Tourette syndrome. After you calm down, search for alternative sources:
- Other systems which still have the older module version installed (copy the folders/files)
- System or file backups which you could pilfer to get the older module files back. Use the $env:PATH variable to guide you towards the folder and file location(s).
- Call a friend who might have an older version installed somewhere, and threaten them with fresh doughnuts or cold beer, until they give in.
If that doesn’t work, go to a gym and beat up a punching bag for an hour.
As it turned out, they’d built a PowerShell-based automation process using internal scripts, and modules available on the PowerShell Gallery. Nothing unusual about that; it is what it was intended for. However, they had also built-in an automatic “update all modules” task at the beginning of their script.
This is a major no-no, because it violates basic “change control” rules. Every change (emphasis on “every“) should (read: must) be tested prior to applying in a production environment. Making the update process part of the production workflow automatically breaks that rule. And in their case, the module they were using was updated to deprecate a parameter on a particular function, which crashed their particular process.
Be careful not to confuse what I’m saying with automated CI/CD pipelines (dev > test > prod). This is merging external changes into a production environment; skipping dev and test entirely. In a nutshell, if you follow standard change control practices, you should rarely, if ever, encounter this situation.
Long story short (like I’m any good at short stories), they couldn’t locate a local copy of the older version and didn’t have a suitable backup to search, but the older version of the module was available in PS Gallery, so they went with scenario B.
Then the angry pack of wolves climbed in through the bedroom window in the middle of the night and ate every single one of them. Oh wait, wrong story…
And they lived happily ever after. The end.