Save-PSResource doesn't install the correct version.
Prerequisites
- [X] Write a descriptive title.
- [X] Make sure you are able to repro it on the latest released version
- [X] Search the existing issues.
- [X] Refer to the FAQ.
- [X] Refer to Differences between Windows PowerShell 5.1 and PowerShell.
Steps to reproduce
I am experiencing a problem with Save-PSResource. When installing a specific version of a module from a NuGet server, it doesn't take the one specified.
Steps to reproduce:
- Have one powershell module in a NuGet server with two different versions published, like '2024.5.20.1' and 2024.5.20.12'
- Download the module with the cmdlet:
Save-PSResource -Name ExampleModule -Version [2024.5.20.1] -Repository ExampleRepository -Path C:\Users\ExampleUser\Documents -SkipDependencyCheck
Expected behavior
ExampleModule installed in:
C:\Users\ExampleUser\Documents\ExampleModule\2024.5.20.1\ExampleModule.psd1
C:\Users\ExampleUser\Documents\ExampleModule\2024.5.20.1\ExampleModule.psm1
Inside the ExampleModule.psd1, the field ModuleVersion with the correct version, in this case '2024.5.20.1'
Actual behavior
ExampleModule installed in:
C:\Users\ExampleUser\Documents\ExampleModule\2024.5.20.1\ExampleModule.psd1
C:\Users\ExampleUser\Documents\ExampleModule\2024.5.20.1\ExampleModule.psm1
Inside the ExampleModule.psd1, the field ModuleVersion with an incorrect version, in this case '2024.5.20.12'
Error details
No response
Environment data
PSVersion 7.4.2
PSEdition Core
GitCommitId 7.4.2
OS Microsoft Windows 10.0.20348
Platfor Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0....}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
Visuals
No response
I could not reproduce:
$ Save-PSResource -Name PSWSMan -Version 2.3.0 -Path ./Downloads/ -IncludeXml
$ tree -d ./Downloads/PSWSMan/
./Downloads/PSWSMan/
└── 2.3.0
├── bin
│ ├── glibc-1.0
│ ├── glibc-1.1
│ ├── glibc-3
│ ├── macOS-1.1
│ ├── macOS-3
│ ├── musl-1.1
│ └── musl-3
└── en-US
Its not the same scenario. I think the problem is that instead of taking the version '2024.5.20.1' as exact version, is taking it as minimum version. That's why then the version '2024.5.20.12' is taken.
Its not the same scenario.
A did not find modules with similar versions:
$ Save-PSResource -Name PSWriteColor -Version 0.7 -Path ./Downloads/ -IncludeXml
$ Save-PSResource -Name PSWriteColor -Version 0.71 -Path ./Downloads/ -IncludeXml
$ (dir ./Downloads/PSWriteColor/).Name
0.7
0.71
I also cannot reproduce the problem, at least with the PSWriteColor module.
The -Version parameter is explicitly documented as being version-exact (no need for [...] enclosure), and that to get the minimum-compatible-version behavior you'd have to use something like '[1.0.0,]' (note the comma).
On second thought:
-
The Package Versioning rules seem to be based on semver version numbers, which are limited to three components, with an optional suffix.
-
Therefore,
2024.5.20.1is not a valid semver ([semver]) version number (but is a valid[version]number).
I wonder if the problem is related to that, and how such invalid-as-semver version numbers are de facto / should be handled.
Example module from PowerShell Gallery with NuGet versioning (four digits vs. semver three, ref: https://learn.microsoft.com/en-us/nuget/concepts/package-versioning?tabs=semver20sort#where-nugetversion-diverges-from-semantic-versioning):
Older than latest version:
Using `-Version '1.0.1.314'` works as expected:
PS > $DebugPreference = 'Continue'; Save-PSResource -Repository 'PSGallery' -TrustRepository -SkipDependencyCheck -Name 'Intune.USB.Creator' -Version '1.0.1.314' -Path 'C:\Users\olavb\Desktop\Testin'
DEBUG: In SavePSResource::ProcessSaveHelper()
DEBUG: In InstallHelper::BeginInstallPackages()
DEBUG: Parameters passed in >>> Name: 'Intune.USB.Creator'; VersionRange: '1.0.1.314'; NuGetVersion: '1.0.1.314'; VersionType: 'SpecificVersion'; Version: '1.0.1.314'; Prerelease: 'False'; Repository: 'PSGallery'; AcceptLicense: 'True'; Quiet: 'False'; Reinstall: 'True'; TrustRepository: 'True'; NoClobber: 'False'; AsNupkg: 'False'; IncludeXml 'False'; SavePackage 'True'; TemporaryPath ''; SkipDependencyCheck: 'True'; AuthenticodeCheck: 'False'; PathsToInstallPkg: 'C:\Users\olavb\Desktop\Testin'; Scope ''
DEBUG: In InstallHelper::ProcessRepositories()
DEBUG: In InstallHelper::InstallPackages()
DEBUG: In InstallHelper::InstallPackage()
DEBUG: In V2ServerAPICalls::FindVersion()
DEBUG: In V2ServerAPICalls::HttpRequestCall()
DEBUG: Request url is 'https://www.powershellgallery.com/api/v2/FindPackagesById()?$filter=Id+eq+%27Intune.USB.Creator%27+and+NormalizedVersion+eq+%271.0.1.314%27&$inlinecount=allpages&id=%27Intune.USB.Creator%27'
DEBUG: Count from response is '1'
DEBUG: In V2ServerAPICalls::InstallVersion()
DEBUG: In V2ServerAPICalls::HttpRequestCallForContent()
DEBUG: Request url is 'https://www.powershellgallery.com/api/v2/package/Intune.USB.Creator/1.0.1.314'
DEBUG: In InstallHelper::TryInstallToTempPath()
DEBUG: In InstallHelper::DeleteExtraneousFiles()
DEBUG: Deleting 'C:\Users\olavb\AppData\Local\Temp\3df2f957-c6ce-4b30-895b-232483e64984\intune.usb.creator\1.0.1.314\Intune.USB.Creator.nuspec'
DEBUG: Deleting 'C:\Users\olavb\AppData\Local\Temp\3df2f957-c6ce-4b30-895b-232483e64984\intune.usb.creator\1.0.1.314\[Content_Types].xml'
DEBUG: Deleting 'C:\Users\olavb\AppData\Local\Temp\3df2f957-c6ce-4b30-895b-232483e64984\intune.usb.creator\1.0.1.314\_rels'
DEBUG: Deleting 'C:\Users\olavb\AppData\Local\Temp\3df2f957-c6ce-4b30-895b-232483e64984\intune.usb.creator\1.0.1.314\package'
DEBUG: In InstallHelper::TryMoveInstallContent()
DEBUG: In InstallHelper::MoveFilesIntoInstallPath()
PS>
Using `-Version [1.0.1.314]` worked too in my testing (as in, did install that exact version):
PS > $DebugPreference = 'Continue'; Save-PSResource -Repository 'PSGallery' -TrustRepository -SkipDependencyCheck -Name 'Intune.USB.Creator' -Version [1.0.1.314] -Path 'C:\Users\olavb\Desktop\Testin'
DEBUG: In SavePSResource::ProcessSaveHelper()
DEBUG: In InstallHelper::BeginInstallPackages()
DEBUG: Parameters passed in >>> Name: 'Intune.USB.Creator'; VersionRange: '[1.0.1.314]'; NuGetVersion: ''; VersionType: 'VersionRange'; Version: '[1.0.1.314]'; Prerelease: 'False'; Repository: 'PSGallery'; AcceptLicense: 'True'; Quiet: 'False'; Reinstall: 'True'; TrustRepository: 'True'; NoClobber: 'False'; AsNupkg: 'False'; IncludeXml 'False'; SavePackage 'True'; TemporaryPath ''; SkipDependencyCheck: 'True'; AuthenticodeCheck: 'False'; PathsToInstallPkg: 'C:\Users\olavb\Desktop\Testin'; Scope ''
DEBUG: In InstallHelper::ProcessRepositories()
DEBUG: In InstallHelper::InstallPackages()
DEBUG: In InstallHelper::InstallPackage()
DEBUG: In V2ServerAPICalls::FindVersionGlobbing()
DEBUG: In V2ServerAPICalls::FindVersionGlobbing()
DEBUG: In V2ServerAPICalls::HttpRequestCall()
DEBUG: Request url is 'https://www.powershellgallery.com/api/v2/FindPackagesById()?$filter=NormalizedVersion+ge+%271.0.1.314%27+and+NormalizedVersion+le+%271.0.1.314%27+and+IsPrerelease+eq+false+and+Id+eq+%27Intune.USB.Creator%27&$inlinecount=allpages&$skip=0&$orderby=NormalizedVersion+desc&id=%27Intune.USB.Creator%27'
DEBUG: In V2ServerAPICalls::InstallVersion()
DEBUG: In V2ServerAPICalls::HttpRequestCallForContent()
DEBUG: Request url is 'https://www.powershellgallery.com/api/v2/package/Intune.USB.Creator/1.0.1.314'
DEBUG: In InstallHelper::TryInstallToTempPath()
DEBUG: In InstallHelper::DeleteExtraneousFiles()
DEBUG: Deleting 'C:\Users\olavb\AppData\Local\Temp\7b6a0df7-cdec-4637-9554-5c390d37609a\intune.usb.creator\1.0.1.314\Intune.USB.Creator.nuspec'
DEBUG: Deleting 'C:\Users\olavb\AppData\Local\Temp\7b6a0df7-cdec-4637-9554-5c390d37609a\intune.usb.creator\1.0.1.314\[Content_Types].xml'
DEBUG: Deleting 'C:\Users\olavb\AppData\Local\Temp\7b6a0df7-cdec-4637-9554-5c390d37609a\intune.usb.creator\1.0.1.314\_rels'
DEBUG: Deleting 'C:\Users\olavb\AppData\Local\Temp\7b6a0df7-cdec-4637-9554-5c390d37609a\intune.usb.creator\1.0.1.314\package'
DEBUG: In InstallHelper::TryMoveInstallContent()
DEBUG: In InstallHelper::MoveFilesIntoInstallPath()
PS >
Not an issue? Might be an API issue with whatever backend OP used? I used PSResourceGet v1.0.5 against PSGallery.