I have a module (MyModule) under a non-standard path, i.e. not under the usual locations listed in $env:PSModulePath -split ";"
. I have, however, added the "production" path to MyModule to that environment variable while I continue to work on a "development" copy.
Whilst trying to debug something, I loaded the module (with $VerbosePreference = "Continue"
) using the following command and immediately saw two seemingly contradictory lines of Verbose output:
[D:\Dev\UserA\]> Import-Module D:\Dev\UserA\libs\PowerShell\MyModule
VERBOSE: Loading module from path 'D:\Dev\UserA\libs\PowerShell\MyModule\MyModule.psd1'.
VERBOSE: Loading module from path 'D:\Dev\usera\MyModule2\MyModule.psm1'.
I would like to understand why Import-Module appears to be loading the module twice, especially as the second path is incorrect.
MORE DETAIL:
The folder structure for the module is:
MyModule\MyModule.psd1
MyModule\MyModule.Test-Module.xml
MyModule\MyModule1\MyModule.psm1
MyModule\MyModule2\MyModule.psm1
Note (1) I retained an older "version 1" of this module in a MyModule1 sub-folder and put my updated "version 2" file in a MyModule2 sub-folder and (2) that the .xml file is used by a custom module-testing script to list test cases. I'm pretty sure that the latter can be ignored.
My module manifest (.psd1) file contains the following, with all other lines being blanks or comments:
@{
RootModule = '.\MyModule2\MyModule.psm1'
ModuleVersion = '2.0.0.0'
GUID = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
Author = 'Old Developer (v1.x) & New Developer (v2.x)'
CompanyName = 'MyCompany'
Copyright = '(c) 2013-2015 MyCompany. All rights reserved.'
Description = 'Really useful functions'
FileList = @(
'.\MyModule.psd1'
'.\MyModule.Test-Module.xml'
'.\MyModule1\MyModule.psm1'
'.\MyModule2\MyModule.psm1'
'.\MyModule2\Examples\Archive-FilesWithCompression.ps1'
)
}
Clearly I have used relative paths for the files, esp. the RootModule key; this is necessary as I cannot be sure where the module will be copied when I share it.
Going back to the Verbose output, I can see that the two lines show (1) the correct path to the PSD1 file and (2) an invalid path to the PSM1 file. I did notice that the second path has the username in lower-case, which is how I happened to type it when I Set-Location
before testing. So, it looks like the first path is taken by appending MyModule.psd1 to the path given to the Import-Module
cmdlet and the second is a concatenation of (Get-Location) and the RootModule path.
This only seems to happen to this module. I have others under the same 'root' folder which don't exhibit this behaviour.
Um. OK. I may have worked it out, at least in part...
I had accidentally made a copy of the MyModule2 sub-folder under the location from where I was running the Import-Module cmdlet. Once I removed that folder the verbose output started to make more sense:
I guess this means that when PowerShell resolves the RootModule in the manifest file it looks under the current path first and then the main module folder if nothing is found. I find this counter-intuitive as I'd expect that any relative paths in the manifest would always be relative to the PSD1 file, not the current location.
If I then try to import the module again immediately I get this:
That is, only one "loading module" line, rather than the two lines of verbose output. I then tried the
-Force
switch and got the following:So, it seems that the two lines of verbose output appear when the module is first imported, or forcibly re-imported, but if it is already part of the session then you only see the first line.
Also, I finally spotted that the verbose output differentiated between exporting functions and importing them. The functions are exported in the order that they are defined in the PSM1 file, but are imported in alphabetical order. This suggests a one- or two-stage process is used depending on whether the function definitions are being re-read from the PSM1 file, tying in with whether we see one or two lines of verbose output.
Or, to answer the question more directly, it appears that there are two lines saying "Loading module..." when it needs to read the .psm1 file, and only one line when PowerShell is already aware of the module and its contents.