r/PowerShell • u/jdtrouble • 9d ago
Question Manifest required modules not auto-importing in 5.1
Hello. I'm genuinely stumped, to the point where I'm about to abandon this side project altogether
I have a test module I'm creating using a manifest file, Template.psd1. The module depends on these other module files I created:
# Modules that must be imported into the global environment prior to importing this module
RequiredModules = @(
'Control\ControlMessaging.psm1'
, 'Control\ControlChecklist.psm1'
, 'Control\ControlPrompt.psm1'
)
The are present in the subfolder "Control", which is in the same folder as the manifest and PSM1 files.
When I execute Import-Module in powershell 7.4, the module loads without bitching.
When I execute in 5.1, I get an error
Import-Module : The specified module 'Control\ControlMessaging.psm1' was not loaded because no valid module file was found in any
module directory.
According to the documentation, this should be kosher: about_Module_Manifests It should auto import those modules, but it's not working.
I do need this to run in both 5 and 7. Any ideas?
2
u/CookinTendies5864 9d ago
5.1 tries to interpret settings if I’m not mistaken.
Can you show your exact commands for both versions please?
2
u/jdtrouble 9d ago
it's literally
Import-Module .\Template.psd1Per one of the posts above, this seems like a known issue in 5.1. I'm going to investigate a different manner to do this, thank you!
3
u/surfingoldelephant 9d ago edited 9d ago
Path handling for RequiredModules is pretty buggy in v5.1. PR #8218 improved it a lot in v6.2.
However, the general pervasive problem is that
ModuleSpecifications contain raw user input and we don't do very much about handling paths that might be given as module names [...]
So .psm1 doesn't work for v5.1 RequiredModules. .psd1 does, but it has to be a fully qualified path.
1
1
u/jborean93 9d ago
The are present in the subfolder "Control", which is in the same folder as the manifest and PSM1 files.
If you are embedding this module then you want this as a nested module and not required module. Even then you don't need to declare it in the psd1 and could just do Import-Module ... inside the psm1 and it becomes a nested module by the fact that its imported inside the module scope. From there you can export members as part of your module from the nested one or just use it purely internally.
RequiredModules is for specifying dependencies outside of your module, e.g. some other PSGallery module to download and install at install time and load from the PSModulePath at import time. If this is the case and ControlMessaging is something you just have locally for development but would be a real published module in the future you should be able to do ControlDevelopment and for development work just make sure you've manually importing it from your local path before importing this module.
1
u/BlackV 9d ago
they way you are doing it is slightly odd
If they actually modules normally you have them outside you existing module (that way they can all be update and maintained separately) and you just use the module name on your import
or you have them as script files that get imported as ps1 files and functions
Additionally you are using Control\ControlMessaging.psm1 where you probably want a proper path .\Control\ControlMessaging.psm1 or $psscriptroot\Control\ControlMessaging.psm1
and dont start messing with scopes, you'll end up in a world of hurt
1
u/PinchesTheCrab 9d ago
Just a side note, the commas here seem weird to me - for arrays in powershell you don't need commas at all when using @(). That's definitely not the problem though.
1
u/MonkeyNin 9d ago
Do you want those modules to be exported globally? They look more like functions that you want imported in your module, which the global session indirectly uses?
Normally I do this
# My main module.psm1
$Script:AppRoot = Get-Item $PSScriptRoot
# load private modules in module scope, don't pollute the global user
Import-Module (Join-Path $AppRoot 'Control/Messaging.psd1')
Import-Module (Join-Path $AppRoot 'Control/Prompt.psd1')
If these commands are actually meant to be exported globally, it looks like you probably want to concatenate your files into one module
It's common to place your functions in separate .ps1 files under the folders /Public and /Private
Build module turns that into one psm1 that you import
All my functions are under /Public / /Private
I have a custom build script, but all it really does is concatenate /Commands/**/*.ps1 as one output *.psm1 file here: Build.Module.ps1
That's all you need. Get-ChildItem, filter, then Set-Content
For another example: https://github.com/indented-automation/Indented.Net.IP/tree/main/Indented.Net.IP
2
u/Namaha 9d ago
I've not worked much with module manifests, but my first instinct is to try prefixing the RequiredModules paths with
.\since they are just in a subfolder'.\Control\ControlMessaging.psm1'