1

I have a build script that depends on an older version of one of our modules. Version 1.0.1. I added -MaximumVersion 1.0.1 to the Import-Module command. When the build script runs it fails and error shows that it is running code in version 2.1.0 of the module.

Import-Module DrilQuip.Build -MaximumVersion 1.0.1 -Force

Creating next version number... The property 'VersionFilePath' cannot be found on this object. Verify that the property exists. At C:\Users\svcTFSBuildProd\Documents\WindowsPowerShell\Modules\DrilQuip.Build\ 2.1.0\DrilQuip.Build.psm1:253 char:5

I have tried with and without the -Force switch but that makes no difference.

I used Get-Module DrilQuip.Build -ListAvailable to confirm that version 1.0.1 is present on the computer.

How can I insure that the script imports and uses the older version of the modules?

Update 1

Added -Verbose switch to get more details about what is happening. Here are the results:

VERBOSE: Loading module from path 'C:\Program Files\WindowsPowerShell\Modules\DrilQuip.Build\1.0.1\DrilQuip.Build.psd1'. VERBOSE: Populating RepositorySourceLocation property for module DrilQuip.Build.

Creating next version number... The property 'VersionFilePath' cannot be found on this object. Verify that the property exists. At C:\Users\svcTFSBuildProd\Documents\WindowsPowerShell\Modules\DrilQuip.Build\ 2.1.0\DrilQuip.Build.psm1:253 char:5 + $Matches = Select-String -Path $global:BuildConfig.VersionFilePat ...

This shows that the same module has been installed into 2 different locations. The location C:\Users\svcTFSBuildProd... seems to trump the location C:\Program Files\WindowsPowerShell...

I think this has to do with Machine vs User scope on the module installation. I'll go back and remove the User scoped modules and install all versions of the module with Machine scope and see if that helps.

Update 2

I removed all of the versions of the module from user scope folder and then tried the script again. It is still failing but now both versions of the module are coming from the same module folder location.

VERBOSE: Loading module from path 'C:\Program Files\WindowsPowerShell\Modules\DrilQuip.Build\1.0.1\DrilQuip.Build.psd1'. VERBOSE: Populating RepositorySourceLocation property for module DrilQuip.Build. Creating next version number... The property 'VersionFilePath' cannot be found on this object. Verify that the property exists. At C:\Program Files\WindowsPowerShell\Modules\DrilQuip.Build\2.0.4\DrilQuip.Build.psm1:251 char:5

Since the new version is still trumping the max version I requested my theory that user scope trumps machine scope is not the real problem. Something else is going on.

I ran Get-Module -Name DrilQuip.Build -ListAvailable again and I notice that the ModuleType is different. On version 1.0.1 the type is Manifest but on versions 1.1.1 and 2.0.4 the type is Script. Maybe this difference is causing the problem.

ModuleType Version    Name          
---------- -------    ----          
Script     2.0.4      DrilQuip.Build
Script     1.1.1      DrilQuip.Build
Manifest   1.0.1      DrilQuip.Build

I will remove all of the modules and reinstall them from the repository.

mklement0
  • 382,024
  • 64
  • 607
  • 775
Matthew MacFarland
  • 2,413
  • 3
  • 26
  • 34
  • 1
    Add `-Verbose` to the `Import-Module` call to see if it at least claims to be loading the right version at that point. Conceivably, later code imports a newer version of the module, e.g. via a `using module` statement. – mklement0 Feb 28 '19 at 03:09
  • What if you try to load the specific module? Get-Module DrilQuip.Build -ListAvailable | Where-Object { $_.Version -eq "1.0.1" } | Import-Module -Force – halv Feb 28 '19 at 13:01
  • 1
    @mklement0 That's a very good troubleshooting suggestion! I added the -Verbose switch and it confirms that version 1.0.1 is being loaded but then the code that calls the function is still getting version 2.1.0 according to the error output. I added the details to the update section of my question. – Matthew MacFarland Feb 28 '19 at 14:44

1 Answers1

1

The older version of the module 1.0.1 has the type Manifest and all the versions after that are type Script. The next version of the module 1.0.2 is also compatible with my build script so I changed the -MaximumVersion parameter to 1.0.2.

Before trying this out I also uninstalled all versions of the module on the computer and then installed just versions 1.0.2 and 2.1.0 that are really needed. I ran PowerShell as administrator so both modules installed into the folder C:\Program Files\WindowsPowerShell\Modules

PS C:\Program Files\WindowsPowerShell\Modules\DrilQuip.Build> get-module DrilQuip.Build -li

    Directory: C:\Program Files\WindowsPowerShell\Modules
ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Script     2.1.0      DrilQuip.Build                      {Start-Build, Write-FileCopyResult, Invoke-MSBuild, New-Da...
Script     1.0.2      DrilQuip.Build                      {Get-NextVersion, Set-TfsWorkspaceFileTime}

After these changes the build script works and uses the 1.0.2 version of the code as expected.

VERBOSE: Loading module from path 'C:\Program 
Files\WindowsPowerShell\Modules\DrilQuip.Build\1.0.2\DrilQuip.Build.psd1'.
VERBOSE: Populating RepositorySourceLocation property for module 
DrilQuip.Build.
VERBOSE: Loading module from path 'C:\Program 
Files\WindowsPowerShell\Modules\DrilQuip.Build\1.0.2\DrilQuip.Build.psm1'.
VERBOSE: Importing function 'Get-NextVersion'.
VERBOSE: Importing function 'Set-TfsWorkspaceFileTime'.

Creating next version number...
New version: 10.2.10928.11004

Based on mklement0's comment it seems that whole problem is that version 1.0.1 was not setup correctly and so no functions got imported. The verbose output from Import-Module confirms that. When the script called the function Get-NextVersion PowerShell used module auto loading to find and load a version of the module that did have the function.

Version 1.0.1 was missing a value for RootModule in the manifest. That error was fixed in version 1.0.2. The module uses Export-ModuleMember to export the functions instead of the FunctionsToExport setting in the manifest. Since 1.0.1 did not have root module set to the psm1 file it had no way to export the functions..

Matthew MacFarland
  • 2,413
  • 3
  • 26
  • 34
  • A `Manifest` module is one that has no `RootModule` (obsolete: `ModuleToProcess`) entry in its manifest file (`*.psd1`), which normally requires the `NestedModules` to be populated. If you try your `1.0.1` module in isolation, does it actually work? Note that your verbose output when loading `1.0.1` doesn't show any commands being imported into the session. – mklement0 Feb 28 '19 at 17:14
  • So what may have happened is this: your import of `1.0.1` was successful, but _no commands were added to the session_. When you later tried to execute a command that you _thought_ was imported via `1.0.1`, the module auto-loading mechanism may have discovered that command and then implicitly loaded the _most recent_ module that contains that command. – mklement0 Feb 28 '19 at 17:15
  • 1
    @mklement0 That sounds like a very good explanation for what really happened. – Matthew MacFarland Feb 28 '19 at 18:41