r/PowerShell • u/tingnossu • 19d ago
Information third-party PS modules and the gotchas nobody warns you about
been burnt a few times now pulling in modules from the Gallery for managing third-party software and figured it's worth talking about. the big one for me was version conflicts. had a module pinned at one version in prod and a totally different one on dev because someone did an Install-Module without specifying -RequiredVersion. took way too long to figure out why the same script was behaving differently across environments. now I just always pin versions and keep a private repo rather than pulling straight from Gallery. worth calling out if you're still on MSOnline or the old AzureAD module - those are fully gone now, so if you haven't migrated to Microsoft.Graph yet that's going to be your most urgent version conflict to deal with. learned that one the hard way when automation started failing in prod. the other thing I didn't expect was how modules auto-load from PSModulePath without much fanfare. if you've got a sketchy or outdated module sitting somewhere in that path it can get pulled in without you realising. I've started being a lot more deliberate about Import-Module with explicit paths and setting $PSModuleAutoLoadingPreference to None in scripts that need to be predictable. also worth auditing what's actually in your module paths occasionally, especially on shared systems. working with stuff like PowerCLI or any vendor-specific module adds another layer too. they sometimes ship with their own dependencies that conflict with things you already have loaded. had a fun afternoon where PowerCLI's version of a shared assembly was fighting with something else in the session. ended up having to run it in a separate PS process just to isolate it. anyone else run into that kind of thing with vendor modules and found a cleaner way to handle it?
6
u/pantherghast 19d ago
Looks like you could use a module that will paragraph your wall of text.
1
u/tingnossu 18d ago
touché, spent so long untangling MSOnline and AzureAD migration chaos that basic formatting went out the window lol. dependency hell will do that to you.
3
u/420GB 19d ago
I'm pretty sure you can just use the #Requires statement to specify a required version of a module. If you just did that you should have had no issues.
1
u/tingnossu 18d ago
Yeah #Requires helps and will actually throw a terminating error if the module isn't there, but it doesn't guarantee runtime API compatibility, had scripts pass, the version check just fine and then blow up anyway because the module's internals changed between versions, especially after the MSOnline and AzureAD forced migrations.
1
u/cottonycloud 19d ago
I don't really face the problem that you have because my modules don't have much overlap and I don't use as many. Usually, my development environment isn't version-pinned but production is.
1
u/tingnossu 18d ago
Keeping dev loose and prod pinned is exactly how we run it too, and even with minimal, overlap we, still hit an assembly conflict once from two modules shipping different versions of the same. NET dependency into the same session.
1
u/cottonycloud 18d ago
It really sucks when that happens. Wish there was something similar to pyproject.toml like Python…
0
u/BlackV 19d ago edited 19d ago
Sir, Please Formatting in your posts (for the old and blind people like me)
the big one for me was version conflicts. had a module pinned at one version in prod and a totally different one on dev because someone did an
Install-Modulewithout specifying-RequiredVersion
that is on you, your script should specify a module and version if a version is required
Install a new version of the module (and seeing what breaks) is EXACTLY why you have DEV, test the new version then move to prod
this also has 0 to do with 3rd party module, this covers ALL modules 1st, 2nd, 3rd
worth calling out if you're still on MSOnline or the old AzureAD module - those are fully gone now
again as per your previous post those are super super deprecated and should have been used in like the last 3? years, not worth calling out as they shouldn't function regardless
the other thing I didn't expect was how modules auto-load from PSModulePath without much fanfare
this has been the default behaviors since PS3 ? maybe 4, a further complication to this is powershell version and where you store your modules
ps 7 looks in
C:\WINDOWS\system32\WindowsPowerShell\v1.0\ModulesC:\Program Files\WindowsPowerShell\ModulesC:\program files\powershell\7\Modules- FFFFFFFFFUUUUUUUUU why did you add this MS/powershell teamC:\Program Files\PowerShell\ModulesC:\Users\<username>\Documents\PowerShell\ModulesC:\Users\<username>\OneDrive\Documents\PowerShell\Modules- Or onedrive/google drive/home drive/etc *C:\Users\<username>\Documents\WindowsPowerShell\ModulesC:\Users\<username>\OneDrive\WindowsDocuments\PowerShell\Modules- Or onedrive/google drive/home drive/etc
ps 5 looks in
C:\WINDOWS\system32\WindowsPowerShell\v1.0\ModulesC:\Program Files\WindowsPowerShell\ModulesC:\Users\<username>\Documents\WindowsPowerShell\ModulesC:\Users\<username>\OneDrive\WindowsDocuments\PowerShell\Modules- Or onedrive/google drive/home drive/etc
that's just x64, x86 adds the additional 32bit folders too, also include and custom module paths you've added
but you should be aware of your required modules and versions
had a fun afternoon where PowerCLI's version of a shared assembly was fighting with something else in the session
I have not used vmware powercli in ages, it was always one of the best behaved and designed modules, but you can confirm a modules dependencies (assembly wise) in its properties (again not limited to 3rd party modules, ms graph modules have been a chronic pain point for this)
There was a good post/reply in here the other day about module assembly version issues and how to work around them
I think there is even a module that will find this for you
the other thing you have not mentioned with additional modules is name overlap, import your powercli modules and run get-vm do the same with the hyperv module and then do the same again with the virtual machine manager modules (and possibly proxmox), you can address this by being specific and using the fully qualified name hyperv\get-vm, vmware.powercli\get-vm and so on
1
u/dodexahedron 19d ago
C:\program files\powershell\7\Modules - FFFFFFFFFUUUUUUUUU why did you add this MS/powershell team
For side-by-side installation of modules with system scope, on different powershell versions.
If you ever have powershell and powershell-preview installed at the same time, you'll see that in action. And you will both appreciate it for the separation and curse it every time you forget which one you installed what on.
1
u/tingnossu 18d ago
fair point, threw this together between IR calls and it shows, cleaning it up now.
-1
u/Apprehensive-Tea1632 19d ago
Nope. Ps only has the one AppDomain so side by side (sxs) doesn’t work.
See if it’ll work using jobs- these are put into dedicated runspaces and a runspace is basically another powershell instance (much like multithreaded Perl).
This means overhead, and as runspaces are isolated, you need to serialize input and output. Type information is lost, so if you need that, you’ll have to rebuild OO using initial values you need to pass from the runspace.
Ex, pass .fullname to identify a file system object across the runspace boundary and then use get-item to get the filesystemobject instance.
Or, well, just start a new process. Of course you’ll still need a way to pass results.
1
u/tingnossu 17d ago
Worth clarifying though, that single AppDomain limitation is really a Windows PowerShell 5. 1 problem.
7
u/KevMar Community Blogger 19d ago
I always try not to pin versions but it always bites me eventually and everything gets pinned in the end. I like to mirror modules into an internal psrepository to gate when new version are introduced into the environment.
The trick that you are looking for next is to use save-module to a local folder and set your $PSModuleRoot to that to isolate it from any other modules already on the system. All my scheduled stuff and pipeline stuff does that (if I don't need any system modules). This way it doesn't matter if different stuff uses different versions from your scripts.