diff --git a/src/System.Management.Automation/engine/Modules/ImportModuleCommand.cs b/src/System.Management.Automation/engine/Modules/ImportModuleCommand.cs index dbd058cab1b..c4fdf96de92 100644 --- a/src/System.Management.Automation/engine/Modules/ImportModuleCommand.cs +++ b/src/System.Management.Automation/engine/Modules/ImportModuleCommand.cs @@ -986,14 +986,28 @@ private PSModuleInfo ImportModule_RemotelyViaPsrpSession_SinglePreimportedModule // import the proxy module just as any other local module // object[] oldArgumentList = this.ArgumentList; + Version originalBaseMinimumVersion = BaseMinimumVersion; + Version originalBaseMaximumVersion = BaseMaximumVersion; + Version originalBaseRequiredVersion = BaseRequiredVersion; try { this.ArgumentList = new object[] { psSession }; + + // The correct module version has already been imported from the remote session and created locally. + // The locally created module always has a version of 1.0 regardless of the actual module version + // imported from the remote session, and version checking is no longer needed and will not work while + // importing this created local module. + BaseMinimumVersion = null; + BaseMaximumVersion = null; + BaseRequiredVersion = null; ImportModule_LocallyViaName(importModuleOptions, wildcardEscapedPsd1Path); } finally { this.ArgumentList = oldArgumentList; + BaseMinimumVersion = originalBaseMinimumVersion; + BaseMaximumVersion = originalBaseMaximumVersion; + BaseRequiredVersion = originalBaseRequiredVersion; } // diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/Import-Module.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/Import-Module.Tests.ps1 index a1c4e134920..5e2d92c8c80 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Core/Import-Module.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/Import-Module.Tests.ps1 @@ -21,10 +21,16 @@ { Import-Module -ModuleInfo $a } | Should Not Throw (Get-Module -Name $moduleName).Name | Should Be $moduleName } + + It "should be able to load an already loaded module" { + Import-Module $moduleName + { $script:module = Import-Module $moduleName -PassThru } | Should Not Throw + Get-Module -Name $moduleName | Should Be $script:module + } } Describe "Import-Module with ScriptsToProcess" -Tags "CI" { - + BeforeAll { $moduleRootPath = Join-Path $TestDrive 'TestModules' New-Item $moduleRootPath -ItemType Directory -Force | Out-Null diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/RemoteImportModule.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/RemoteImportModule.Tests.ps1 new file mode 100644 index 00000000000..bc75cfd8b21 --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/RemoteImportModule.Tests.ps1 @@ -0,0 +1,111 @@ +Describe "Remote import-module tests" -Tags 'Feature','RequireAdminOnWindows' { + + BeforeAll { + $originalDefaultParameterValues = $PSDefaultParameterValues.Clone() + $modulePath = "$testdrive\Modules\TestImport" + if (!$IsWindows) { + $PSDefaultParameterValues["it:skip"] = $true + } else { + $pssession = New-RemoteSession + Invoke-Command -Session $pssession -ScriptBlock { $env:PSModulePath += ";${using:testdrive}" } + # pending https://github.com/PowerShell/PowerShell/issues/4819 + # $cimsession = New-RemoteSession -CimSession + $null = New-Item -ItemType Directory -Path $modulePath + Set-Content -Path $modulePath\testimport.psm1 -Value "function test-hello { 'world' }" + New-ModuleManifest -Path $modulePath\testimport.psd1 -ModuleVersion 1.2.3 -RootModule testimport.psm1 -FunctionsToExport "test-hello" ` + -HelpInfoUri "https://help" -Guid (New-Guid) + } + } + + AfterAll { + $global:PSDefaultParameterValues = $originalDefaultParameterValues + if ($IsWindows) { + $pssession | Remove-PSSession -ErrorAction SilentlyContinue + } + } + + BeforeEach { + Remove-Module TestImport -Force -ErrorAction SilentlyContinue + } + + It "Import-Module can be called as an API with '' = ''" -TestCases @( + @{parameter = "Global" ; value = $true}, + @{parameter = "Global" ; value = $false}, + @{parameter = "Prefix" ; value = "Hello"}, + @{parameter = "Name" ; value = "foo","bar"}, + @{parameter = "FullyQualifiedName" ; value = @{ModuleName='foo';RequiredVersion='0.0'},@{ModuleName='bar';RequiredVersion='1.1'}}, + @{parameter = "Assembly" ; script = { [System.AppDomain]::CurrentDomain.GetAssemblies() | Select-Object -First 2 }} + @{parameter = "Function" ; value = "foo","bar"}, + @{parameter = "Cmdlet" ; value = "foo","bar"}, + @{parameter = "Variable" ; value = "foo","bar"}, + @{parameter = "Alias" ; value = "foo","bar"}, + @{parameter = "Force" ; value = $true}, + @{parameter = "Force" ; value = $false}, + @{parameter = "PassThru" ; value = $true}, + @{parameter = "PassThru" ; value = $false}, + @{parameter = "AsCustomObject" ; value = $true}, + @{parameter = "AsCustomObject" ; value = $false}, + @{parameter = "MinimumVersion" ; value = "1.2.3"}, + @{parameter = "MaximumVersion" ; value = "3.2.1"}, + @{parameter = "RequiredVersion" ; value = "1.1.1"}, + @{parameter = "ArgumentList" ; value = "hello","world"}, + @{parameter = "DisableNameChecking"; value = $true}, + @{parameter = "DisableNameChecking"; value = $false}, + @{parameter = "NoClobber" ; value = $true}, + @{parameter = "NoClobber" ; value = $false}, + @{parameter = "Scope" ; value = "Local"}, + @{parameter = "Scope" ; value = "Global"}, + @{parameter = "PSSession" ; value = $pssession}, + # @{parameter = "CimSession" ; value = $cimsession}, + @{parameter = "CimResourceUri" ; value = "http://foo/"}, + @{parameter = "CimNamespace" ; value = "foo"} + ) { + param($parameter, $value, $script) + + $importModuleCommand = [Microsoft.PowerShell.Commands.ImportModuleCommand]::new() + if ($script -ne $null) { + $value = & $script + } + $importModuleCommand.$parameter = $value + if ($parameter -eq "FullyQualifiedName") { + $importModuleCommand.FullyQualifiedName.Count | Should BeExactly 2 + $importModuleCommand.FullyQualifiedName | Should BeOfType "Microsoft.PowerShell.Commands.ModuleSpecification" + $importModuleCommand.FullyQualifiedName[0].Name | Should Be "foo" + $importModuleCommand.FullyQualifiedName[0].RequiredVersion | Should Be "0.0" + $importModuleCommand.FullyQualifiedName[1].Name | Should Be "bar" + $importModuleCommand.FullyQualifiedName[1].RequiredVersion | Should Be "1.1" + } else { + $importModuleCommand.$parameter | Should BeExactly $value + } + } + + It "Import-Module can import over remote session: " -TestCases @( + @{ test = "pssession" ; parameters = @{Name="TestImport";PSSession=$pssession}}, +# @{ test = "cimsession" ; parameters = @{Name="TestImport";CimSession=$cimsession}}, + @{ test = "minimumversion" ; parameters = @{Name="TestImport";PSSession=$pssession;MinimumVersion="1.0";Force=$true}}, + @{ test = "requiredversion" ; parameters = @{Name="TestImport";PSSession=$pssession;RequiredVersion="1.2.3"}}, + @{ test = "maxiumversion" ; parameters = @{Name="TestImport";PSSession=$pssession;MaximumVersion="2.0"}}, + @{ test = "invalid miniumversion" ; parameters = @{Name="TestImport";PSSession=$pssession;MinimumVersion="2.0"}; + errorid = "Modules_ModuleWithVersionNotFound,Microsoft.PowerShell.Commands.ImportModuleCommand,Microsoft.PowerShell.Commands.ImportModuleCommand"}, + @{ test = "invalid maximumversion" ; parameters = @{Name="TestImport";PSSession=$pssession;MaximumVersion="1.0"}; + errorid = "Modules_ModuleWithVersionNotFound,Microsoft.PowerShell.Commands.ImportModuleCommand,Microsoft.PowerShell.Commands.ImportModuleCommand"}, + @{ test = "fullyqualifiedname" ; parameters = @{FullyQualifiedName=@{Modulename="TestImport"; RequiredVersion="1.2.3"};PSSession=$pssession}} + ) { + param ($test, $parameters, $errorid) + + Invoke-Command -Session $pssession -ScriptBlock { $env:PSModulePath += ";$(Split-Path $using:modulePath)"} + Get-Module TestImport | Should BeNullOrEmpty + if ($errorid) { + { Import-Module @parameters -ErrorAction Stop } | ShouldBeErrorId $errorid + } else { + Import-Module @parameters + $module = Get-Module TestImport + $module.Name | Should BeExactly "TestImport" + + # generated proxy module always uses 1.0 + $module.Version | Should BeExactly "1.0" + + test-hello | Should BeExactly "world" + } + } +}