I recently discovered the ScriptsToProcess member in module manifests and was trying to explore using it to simplify the organization of my subscripts in modules. Instead of having a separate module subscript that loads all my subscripts, I thought it would be more elegant to reuse my existing manifest file to load the subscripts in the ScriptsToProcess member.
It seems to be working for my enums—at least, I think so. My functions aren't working though, and I haven't gotten the module to run far enough to where it tries to instantiate one of its classes.
Example:
PS>New-Item -Path test/test.psm1 -Force
PS>cd test
test.psm1
Function testModule {
callEcho
}
Export-ModuleMember -Function testModule
test.psd1
PS>New-ModuleManifest -Path .\test.psd1 -RootModule .\test.psm1 -ScriptsToProcess .\subscripts\functions.ps1
PS>New-Item -Path subscripts/functions.ps1 -Force
functions.ps1
Function writeEcho {
write-host 'it worked!'
}
Write-Host 'ScriptsToProcess has loaded me'
PS>Import-Module .\test.psd1 -Force
PS>testModule
callEcho : The term 'callEcho' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
My module doesn't have access to the function.
I assume this is intended, so is there another way to go about it, or do I need to make a separate file which dot sources all my subscripts at the start of the module?
Also, will this behavior also apply to classes?
PS5.1.14393
CodePudding user response:
ScriptsToProcess scripts are dot-sourced in the importer's scope, and unless that scope happens to be the global one,[1] your module won't see the definitions.
To dot-source helper scripts in the context of your module, place them in a subdirectory named, say, scripts, then place the following code in your RootModule .psm1 file:
Get-ChildItem $PSScriptRoot/scripts -Filter *.ps1 |
ForEach-Object { . $_.FullName }
Note that unless you expressly export functions defined in these scripts, they'll be visible inside the module only.
As for making enum and class definitions available to the importer:
Define them inside your module and make the importer import the module via using module rather than via Import-Module.
Only use a ScriptsToProcess script to make enums and classes available to the importer if you don't also use them inside the module too.
Note that if you tried to use the same script with both ScriptsToProcess and module-internal dot-sourcing, you'd end up with enums and classes that aren't the same in the two contexts - even though they appear to be.
[1] That is, when you run Import-Module directly from the interactive Powershell prompt (or when you use an equivalent mechanism) - what matters is what scope the importer runs in. This is unrelated to what scope you load the module into, such as with Import-Module -Global
