Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1881,13 +1881,22 @@ protected override void ProcessRecord()

internal override IList<PSModuleInfo> ImportModulesUsingWinCompat(IEnumerable<string> moduleNames, IEnumerable<ModuleSpecification> moduleFullyQualifiedNames, ImportModuleOptions importModuleOptions)
{
IList<PSModuleInfo> moduleProxyList = new List<PSModuleInfo>();
#if !UNIX
var winPSVersionString = Utils.GetWindowsPowerShellVersionFromRegistry();
if (!winPSVersionString.StartsWith("5.1", StringComparison.OrdinalIgnoreCase))
{
string errorMessage = string.Format(CultureInfo.InvariantCulture, Modules.WinCompatRequredVersionError, winPSVersionString);
throw new InvalidOperationException(errorMessage);
}

PSSession WindowsPowerShellCompatRemotingSession = CreateWindowsPowerShellCompatResources();
if (WindowsPowerShellCompatRemotingSession == null)
{
return new List<PSModuleInfo>();
}

var moduleProxyList = ImportModule_RemotelyViaPsrpSession(importModuleOptions, moduleNames, moduleFullyQualifiedNames, WindowsPowerShellCompatRemotingSession, usingWinCompat: true);
moduleProxyList = ImportModule_RemotelyViaPsrpSession(importModuleOptions, moduleNames, moduleFullyQualifiedNames, WindowsPowerShellCompatRemotingSession, usingWinCompat: true);
foreach(PSModuleInfo moduleProxy in moduleProxyList)
{
moduleProxy.IsWindowsPowerShellCompatModule = true;
Expand All @@ -1896,7 +1905,7 @@ internal override IList<PSModuleInfo> ImportModulesUsingWinCompat(IEnumerable<st
string message = StringUtil.Format(Modules.WinCompatModuleWarning, moduleProxy.Name, WindowsPowerShellCompatRemotingSession.Name);
WriteWarning(message);
}

#endif
return moduleProxyList;
}

Expand Down
38 changes: 38 additions & 0 deletions src/System.Management.Automation/engine/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,41 @@ internal static string GetApplicationBaseFromRegistry(string shellId)

return null;
}

private static string s_windowsPowerShellVersion = null;

/// <summary>
/// Get the Windows PowerShell version from registry.
/// </summary>
/// <returns>
/// String of Windows PowerShell version from registry.
/// </returns>
internal static string GetWindowsPowerShellVersionFromRegistry()
{
if (!string.IsNullOrEmpty(InternalTestHooks.TestWindowsPowerShellVersionString))
{
return InternalTestHooks.TestWindowsPowerShellVersionString;
}

if (s_windowsPowerShellVersion != null)
{
return s_windowsPowerShellVersion;
}

string engineKeyPath = RegistryStrings.MonadRootKeyPath + "\\" +
PSVersionInfo.RegistryVersionKey + "\\" + RegistryStrings.MonadEngineKey;

using (RegistryKey engineKey = Registry.LocalMachine.OpenSubKey(engineKeyPath))
{
if (engineKey != null)
{
s_windowsPowerShellVersion = engineKey.GetValue(RegistryStrings.MonadEngine_MonadVersion) as string;
return s_windowsPowerShellVersion;
}
}

return string.Empty;
}
#endif

internal static string DefaultPowerShellAppBase => GetApplicationBase(DefaultPowerShellShellID);
Expand Down Expand Up @@ -2066,6 +2101,9 @@ public static class InternalTestHooks
// since we can't manipulate the System32 directory in a test
internal static string TestWindowsPowerShellPSHomeLocation;

// A version of Windows PS that is installed on the system; normally this is retrieved from a reg key that is write-protected.
internal static string TestWindowsPowerShellVersionString;

internal static bool ShowMarkdownOutputBypass;

/// <summary>This member is used for internal test purposes.</summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1160,8 +1160,9 @@ private List<RemoteRunspace> CreateRunspacesForUseWindowsPowerShellParameterSet(

NewProcessConnectionInfo connectionInfo = new NewProcessConnectionInfo(this.Credential);
connectionInfo.AuthenticationMechanism = this.Authentication;
#if !UNIX
connectionInfo.PSVersion = new Version(5, 1);

#endif
var typeTable = TypeTable.LoadDefaultTypeFiles();
string runspaceName = GetRunspaceName(0, out int runspaceIdUnused);
remoteRunspaces.Add(RunspaceFactory.CreateRunspace(connectionInfo: connectionInfo,
Expand Down
3 changes: 3 additions & 0 deletions src/System.Management.Automation/resources/Modules.resx
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,9 @@
<data name="WinCompatModuleWarning" xml:space="preserve">
<value>Module {0} is loaded in Windows PowerShell using {1} remoting session; please note that all input and output of commands from this module will be deserialized objects. If you want to load this module into PowerShell Core please use 'Import-Module -SkipEditionCheck' syntax.</value>
</data>
<data name="WinCompatRequredVersionError" xml:space="preserve">
<value>Detected Windows PowerShell version {0}. Windows PowerShell 5.1 is required to load modules using Windows PowerShell compatibility feature. Install Windows Management Framework (WMF) 5.1 from https://aka.ms/WMF5Download to enable this feature.</value>
</data>
<data name="PsModuleOverCimSessionError" xml:space="preserve">
<value>The module {0} cannot be imported over a CimSession. Try using the PSSession parameter of the Import-Module cmdlet.</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,16 @@ Describe "Import-Module from CompatiblePSEditions-checked paths" -Tag "CI" {
New-TestModules -TestCases $successCases -BaseDir $basePath
New-TestModules -TestCases $failCases -BaseDir $basePath

$allModules = ($successCases + $failCases).ModuleName
$allCases = $successCases + $failCases
$allModules = $allCases.ModuleName
$versionTestCases = @()
foreach($versionString in @('1.0','2.0','3.0','4.0','5.0','5.1','5.1.14393.0'))
{
foreach($case in $allCases)
{
$versionTestCases += $case + @{WinPSVersion = $versionString}
}
}

# make sure there are no ImplicitRemoting leftovers from previous tests
Get-Module | Where-Object {$_.PrivateData.ImplicitRemoting} | Remove-Module -Force
Expand Down Expand Up @@ -300,6 +309,24 @@ Describe "Import-Module from CompatiblePSEditions-checked paths" -Tag "CI" {
Import-Module $ModuleName -UseWindowsPowerShell -Force
& "Test-${ModuleName}PSEdition" | Should -Be 'Desktop'
}

It "WinCompat works only with Windows PS 5.1 (when PSEdition <Editions> and WinPSVersion <WinPSVersion>)" -TestCases $versionTestCases -Skip:(-not $IsWindows) {
param($Editions, $ModuleName, $Result, $WinPSVersion)

try {
[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook("TestWindowsPowerShellVersionString", $WinPSVersion)
if ($WinPSVersion.StartsWith('5.1')) {
Import-Module $ModuleName -UseWindowsPowerShell -Force
& "Test-${ModuleName}PSEdition" | Should -Be 'Desktop'
}
else {
{ Import-Module $ModuleName -UseWindowsPowerShell -Force } | Should -Throw -ErrorId "InvalidOperationException"
}
}
finally {
[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook("TestWindowsPowerShellVersionString", $null)
}
}
}

Context "Imports from absolute path" {
Expand Down