From f94699ac92e334b23a05ce615ed8551bc460cf08 Mon Sep 17 00:00:00 2001 From: Mike Richmond Date: Wed, 26 Oct 2016 11:29:45 -0700 Subject: [PATCH 01/12] Adding side-by-side PowerShell Core support to Enable-PSRemoting and the PSSessionConfiguration cmdlets. --- build.psm1 | 13 +- .../engine/InitialSessionState.cs | 4 +- .../remoting/commands/CustomShellCommands.cs | 377 ++++++++++++++---- .../resources/RemotingErrorIdStrings.resx | 14 + 4 files changed, 319 insertions(+), 89 deletions(-) diff --git a/build.psm1 b/build.psm1 index 8e31992d398..5a8aa52d95c 100644 --- a/build.psm1 +++ b/build.psm1 @@ -252,9 +252,20 @@ cmd.exe /C cd /d "$location" "&" "$($vcPath)\vcvarsall.bat" "$Arch" "&" cmake "$ $FilesToCopy = @('pwrshplugin.dll', 'pwrshplugin.pdb') $dstPath = "$PSScriptRoot\src\powershell-win-core" $FilesToCopy | ForEach-Object { - $srcPath = Join-Path (Join-Path (Join-Path (Get-Location) "bin") $Configuration) "CoreClr/$_" + $srcPath = [IO.Path]::Combine((Get-Location), "bin", $Configuration, "CoreClr/$_") + log " Copying $srcPath to $dstPath" Copy-Item $srcPath $dstPath + + if ($_ -match "pwrshplugin.") + { + # Copy the plugin dll to the output directory so that the remoting tests can run out of the default build directory + $tempOptions = New-PSOptions -Configuration ($script:Options).Configuration -Framework ($script:Options).Framework -Runtime ($script:Options).Runtime + $pluginDst = [IO.Path]::GetDirectoryName($tempOptions.Output) # skip the powershell.exe that gets added on the end + New-Item -Type Directory $pluginDst -Force + log " Copying $srcPath to $pluginDst" + Copy-Item $srcPath $pluginDst + } } # Place the remoting configuration script in the same directory diff --git a/src/System.Management.Automation/engine/InitialSessionState.cs b/src/System.Management.Automation/engine/InitialSessionState.cs index 235b1dc943a..30cbcf33d33 100644 --- a/src/System.Management.Automation/engine/InitialSessionState.cs +++ b/src/System.Management.Automation/engine/InitialSessionState.cs @@ -5962,7 +5962,9 @@ private static void InitializeCoreCmdletsAndProviders( {"Connect-PSSession", new SessionStateCmdletEntry("Connect-PSSession", typeof(ConnectPSSessionCommand), helpFile) }, {"Debug-Job", new SessionStateCmdletEntry("Debug-Job", typeof(DebugJobCommand), helpFile) }, {"Disable-PSSessionConfiguration", new SessionStateCmdletEntry("Disable-PSSessionConfiguration", typeof(DisablePSSessionConfigurationCommand), helpFile) }, + {"Disable-PSRemoting", new SessionStateCmdletEntry("Disable-PSRemoting", typeof(DisablePSRemotingCommand), helpFile) }, {"Disconnect-PSSession", new SessionStateCmdletEntry("Disconnect-PSSession", typeof(DisconnectPSSessionCommand), helpFile) }, + {"Enable-PSRemoting", new SessionStateCmdletEntry("Enable-PSRemoting", typeof(EnablePSRemotingCommand), helpFile) }, {"Enable-PSSessionConfiguration", new SessionStateCmdletEntry("Enable-PSSessionConfiguration", typeof(EnablePSSessionConfigurationCommand), helpFile) }, {"Enter-PSHostProcess", new SessionStateCmdletEntry("Enter-PSHostProcess", typeof(EnterPSHostProcessCommand), helpFile) }, {"Enter-PSSession", new SessionStateCmdletEntry("Enter-PSSession", typeof(EnterPSSessionCommand), helpFile) }, @@ -6013,8 +6015,6 @@ private static void InitializeCoreCmdletsAndProviders( {"Where-Object", new SessionStateCmdletEntry("Where-Object", typeof(WhereObjectCommand), helpFile) }, #if !CORECLR {"Add-PSSnapin", new SessionStateCmdletEntry("Add-PSSnapin", typeof(AddPSSnapinCommand), helpFile) }, - {"Disable-PSRemoting", new SessionStateCmdletEntry("Disable-PSRemoting", typeof(DisablePSRemotingCommand), helpFile) }, - {"Enable-PSRemoting", new SessionStateCmdletEntry("Enable-PSRemoting", typeof(EnablePSRemotingCommand), helpFile) }, {"Export-Console", new SessionStateCmdletEntry("Export-Console", typeof(ExportConsoleCommand), helpFile) }, {"Get-PSSnapin", new SessionStateCmdletEntry("Get-PSSnapin", typeof(GetPSSnapinCommand), helpFile) }, {"Remove-PSSnapin", new SessionStateCmdletEntry("Remove-PSSnapin", typeof(RemovePSSnapinCommand), helpFile) }, diff --git a/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs b/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs index 0ef40bd39a1..a223e011a2f 100644 --- a/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs +++ b/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs @@ -107,7 +107,7 @@ function Register-PSSessionConfiguration {{ if ($force) {{ - if (Test-Path WSMan:\localhost\Plugin\""$pluginName"") + if (Test-Path (Join-Path WSMan:\localhost\Plugin ""$pluginName"")) {{ Unregister-PSSessionConfiguration -name ""$pluginName"" -force }} @@ -125,13 +125,15 @@ function Register-PSSessionConfiguration new-item -path WSMan:\localhost\Plugin -file ""$filepath"" -name ""$pluginName"" }} - if ($? -and $runAsUserName) + if ($? -and $runAsUserName) {{ try {{ $runAsCredential = new-object system.management.automation.PSCredential($runAsUserName, $runAsPassword) - set-item -WarningAction SilentlyContinue WSMan:\localhost\Plugin\""$pluginName""\RunAsUser $runAsCredential -confirm:$false + $pluginWsmanRunAsUserPath = [System.IO.Path]::Combine(""WSMan:\localhost\Plugin"", ""$pluginName"", ""RunAsUser"") + set-item -WarningAction SilentlyContinue $pluginWsmanRunAsUserPath $runAsCredential -confirm:$false }} catch {{ - remove-item WSMan:\localhost\Plugin\""$pluginName"" -recurse -force + + remove-item (Join-Path WSMan:\localhost\Plugin ""$pluginName"") -recurse -force write-error $_ # Do not add anymore clean up code after Write-Error, because if EA=Stop is set by user # any code at this point will not execute. @@ -238,7 +240,7 @@ function Register-PSSessionConfiguration }} }} catch {{ - remove-item WSMan:\localhost\Plugin\""$pluginName"" -recurse -force + remove-item (Join-Path WSMan:\localhost\Plugin ""$pluginName"") -recurse -force write-error $_ # Do not add anymore clean up code after Write-Error, because if EA=Stop is set by user # any code at this point will not execute. @@ -279,7 +281,7 @@ function Register-PSSessionConfiguration private const string pluginXmlFormat = @" @@ -485,6 +487,20 @@ protected override void BeginProcessing() ThrowTerminatingError(ioe.ErrorRecord); } } + +#if CORECLR + if (Platform.IsPowerShellCore) + { + string pluginPath = PSSessionConfigurationCommandUtilities.GetWinrmPluginDllPath(); + pluginPath = Environment.ExpandEnvironmentVariables(pluginPath); + if (!System.IO.File.Exists(pluginPath)) + { + PSInvalidOperationException ioe = new PSInvalidOperationException( + StringUtil.Format(RemotingErrorIdStrings.PluginDllMissing, RemotingConstants.PSPluginDLLName)); + ThrowTerminatingError(ioe.ErrorRecord); + } + } +#endif } /// @@ -764,10 +780,11 @@ private string ConstructTemporaryFile(string pluginContent) try { - StreamWriter fileStream = File.CreateText(tmpFileName); - fileStream.Write(pluginContent); - fileStream.Flush(); - fileStream.Dispose(); + using (StreamWriter fileStream = File.CreateText(tmpFileName)) + { + fileStream.Write(pluginContent); + fileStream.Flush(); + } } catch (UnauthorizedAccessException uae) { @@ -988,8 +1005,14 @@ private string ConstructPluginContent(out string srcConfigFilePath, out string d if (string.Equals(procArch, "amd64", StringComparison.OrdinalIgnoreCase) || string.Equals(procArch, "ia64", StringComparison.OrdinalIgnoreCase)) { +#if CORECLR + InvalidOperationException ioe = new InvalidOperationException(RemotingErrorIdStrings.InvalidProcessorArchitecture); + ErrorRecord er = new ErrorRecord(ioe, "InvalidProcessorArchitecture", ErrorCategory.InvalidArgument, Path); + ThrowTerminatingError(er); +#else // syswow64 is applicable only on 64 bit platforms. destPath = destPath.ToLowerInvariant().Replace("\\system32\\", "\\syswow64\\"); +#endif } } @@ -1000,6 +1023,13 @@ private string ConstructPluginContent(out string srcConfigFilePath, out string d destConfigFilePath = destPath; // Copy File. + string destConfigFileDirectory = System.IO.Path.GetDirectoryName(destConfigFilePath); + if (Platform.IsPowerShellCore) + { + // The directory is not auto-created for PowerShell Core. + // The call will create it or return its path if it already exists + System.IO.Directory.CreateDirectory(destConfigFileDirectory); + } File.Copy(srcConfigFilePath, destConfigFilePath, true); initParameters.Append(string.Format(CultureInfo.InvariantCulture, @@ -1241,10 +1271,12 @@ private string ConstructPluginContent(out string srcConfigFilePath, out string d (transportOption as WSManConfigurationOption).ProcessIdleTimeoutSec = 0; } + string psPluginDllPath = PSSessionConfigurationCommandUtilities.GetWinrmPluginDllPath(); + string result = string.Format(CultureInfo.InvariantCulture, pluginXmlFormat, shellName, /* {0} */ - RemotingConstants.PSPluginDLLName, /* {1} */ + psPluginDllPath, /* {1} */ architectureParameter, /* {2} */ initParameters.ToString(), /* {3} */ WSManNativeApi.ResourceURIPrefix + shellName, /* {4} */ @@ -1528,6 +1560,46 @@ internal static string GetRunAsVirtualAccountGroupsString(string[] groups) return string.Join(";", groups); } + /// + /// Returns the default WinRM plugin shell name for this instance of PowerShell + /// + /// + internal static string GetWinrmPluginShellName() + { +#if CORECLR + if (Platform.IsPowerShellCore) + { + // PowerShell Core uses a versioned directory to hold the plugin + Hashtable versionTable = PSVersionInfo.GetPSVersionTable(); + // TODO: This should be PSVersionInfo.PSVersionName once we get + // closer to release. Right now it doesn't support alpha versions. + return System.String.Concat("PowerShell.", (string)versionTable["GitCommitId"]); + } + // else it is WindowsPowerShell for CoreCLR and uses the DefaultShellName +#endif + return RemotingConstants.DefaultShellName; + } + + /// + /// Returns the default WinRM plugin DLL file path for this instance of PowerShell + /// + /// + internal static string GetWinrmPluginDllPath() + { + string pluginDllDirectory = "%windir%\\system32"; +#if CORECLR + if (Platform.IsPowerShellCore) + { + // PowerShell Core uses its versioned directory instead of system32 + Hashtable versionTable = PSVersionInfo.GetPSVersionTable(); + // TODO: This should be PSVersionInfo.PSVersionName once we get + // closer to release. Right now it doesn't support alpha versions. + pluginDllDirectory = System.IO.Path.Combine("%windir%\\system32\\PowerShell", (string)versionTable["GitCommitId"]); + } +#endif + return System.IO.Path.Combine(pluginDllDirectory, RemotingConstants.PSPluginDLLName); + } + #endregion #region Group Conditional SDDL @@ -2493,7 +2565,27 @@ function Unregister-PSSessionConfiguration {{ return }} - + else + {{ + if (($pluginFileName.Value -match 'system32\\{0}') -OR + ($pluginFileName.Value -match 'syswow64\\{0}')) + {{ + # Filter out WindowsPowerShell endpoints when running as PowerShell Core + if ([System.Management.Automation.Platform]::IsPowerShellCore) + {{ + return + }} + }} + else + {{ + # Filter out PowerShell Core endpoints when running as WindowsPowerShell + if (![System.Management.Automation.Platform]::IsPowerShellCore) + {{ + return + }} + }} + }} + $shellsFound++ $shouldProcessTargetString = $targetTemplate -f $_.Name @@ -2717,9 +2809,12 @@ function ExtractPluginProperties([string]$pluginDir, $objectToWriteTo) }} Get-Details $pluginDir $h - - if ($h[""AssemblyName""] -eq ""Microsoft.PowerShell.Workflow.ServiceCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"") {{ - + + # Workflow is not supported in PowerShell Core. Attempting to load the + # assembly results in a FileNotFoundException. + if (![System.Management.Automation.Platform]::IsCoreCLR -AND + $h[""AssemblyName""] -eq ""Microsoft.PowerShell.Workflow.ServiceCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"") {{ + $serviceCore = [Reflection.Assembly]::Load(""Microsoft.Powershell.Workflow.ServiceCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"") if ($null -ne $serviceCore) {{ @@ -2783,18 +2878,37 @@ function ExtractPluginProperties([string]$pluginDir, $objectToWriteTo) $shellNotErrMsgFormat = $args[1] $force = $args[2] $args[0] | ForEach-Object {{ - $shellsFound = 0; - $filter = $_ - Get-ChildItem 'WSMan:\localhost\Plugin\' -Force:$force | Where-Object {{ $_.name -like ""$filter"" }} | ForEach-Object {{ - $customPluginObject = new-object object - $customPluginObject.pstypenames.Insert(0, '{0}') - ExtractPluginProperties ""$($_.PSPath)"" $customPluginObject - # this is powershell based custom shell only if its plugin dll is pwrshplugin.dll - if (($customPluginObject.FileName) -and ($customPluginObject.FileName -match '{1}')) - {{ - $shellsFound++ - $customPluginObject - }} + $shellsFound = 0; + $filter = $_ + Get-ChildItem 'WSMan:\localhost\Plugin\' -Force:$force | ? {{ $_.name -like ""$filter"" }} | ForEach-Object {{ + $customPluginObject = new-object object + $customPluginObject.pstypenames.Insert(0, '{0}') + ExtractPluginProperties ""$($_.PSPath)"" $customPluginObject + # this is powershell based custom shell only if its plugin dll is pwrshplugin.dll + if (($customPluginObject.FileName) -and ($customPluginObject.FileName -match '{1}')) + {{ + # Filter the endpoints based on the typeof PowerShell that is + # executing the cmdlet. + if (($customPluginObject.FileName -match 'system32\\{1}') -OR # WindowsPowerShell + ($customPluginObject.FileName -match 'syswow64\\{1}')) # WOW64 WindowsPowerShell + {{ + # Add WindowsPowerShell endpoints when running as WindowsPowerShell + if (![System.Management.Automation.Platform]::IsPowerShellCore) + {{ + $shellsFound++ + $customPluginObject + }} + }} + else # {1} in another location indicates that it is a PowerShell Core endpoint + {{ + # Add the PowerShell Core endpoint when running as PowerShell Core + if ([System.Management.Automation.Platform]::IsPowerShellCore) + {{ + $shellsFound++ + $customPluginObject + }} + }} + }} }} # end of foreach if (!$shellsFound -and !([System.Management.Automation.WildcardPattern]::ContainsWildcardCharacters($_))) @@ -3019,6 +3133,8 @@ function Set-RunAsCredential{{ [string]$resourceUri, [string]$pluginNotFoundErrorMsg, [string]$pluginNotPowerShellMsg, + [string]$pluginForPowerShellCoreMsg, + [string]$pluginForWindowsPowerShellMsg, [System.Management.Automation.Runspaces.PSSessionConfigurationAccessMode]$accessMode ) {{ @@ -3045,6 +3161,28 @@ function Set-RunAsCredential{{ Write-Error $pluginNotPowerShellMsg return }} + else + {{ + if (($pluginFileName.Value -match 'system32\\{0}') -OR + ($pluginFileName.Value -match 'syswow64\\{0}')) + {{ + # Filter out WindowsPowerShell endpoints when running as PowerShell Core + if ([System.Management.Automation.Platform]::IsPowerShellCore) + {{ + Write-Error $pluginForWindowsPowerShellMsg + return + }} + }} + else + {{ + # Filter out PowerShell Core endpoints when running as WindowsPowerShell + if (![System.Management.Automation.Platform]::IsPowerShellCore) + {{ + Write-Error $pluginForPowerShellCoreMsg + return + }} + }} + }} # set Initialization Parameters $initParametersPath = Join-Path ""$pluginDir"" 'InitializationParameters' @@ -3100,7 +3238,7 @@ function Set-RunAsCredential{{ $null = winrm configsddl $resourceUri }} - # If accessmode is 'Disabled', we don't bother to check the sddl + # If accessmode is Disabled, we do not bother to check the sddl if ([System.Management.Automation.Runspaces.PSSessionConfigurationAccessMode]::Disabled.Equals($accessMode)) {{ return @@ -3181,7 +3319,7 @@ function Set-RunAsCredential{{ }} }} -Set-PSSessionConfiguration $args[0] $args[1] $args[2] $args[3] $args[4] $args[5] $args[6] $args[7] $args[8] $args[9] +Set-PSSessionConfiguration $args[0] $args[1] $args[2] $args[3] $args[4] $args[5] $args[6] $args[7] $args[8] $args[9] $args[10] $args[11] "; private const string initParamFormat = @""; private const string privateDataFormat = @"{0}"; @@ -3439,6 +3577,8 @@ protected override void ProcessRecord() string shellNotFoundErrorMsg = StringUtil.Format(RemotingErrorIdStrings.CSCmdsShellNotFound, shellName); string shellNotPowerShellMsg = StringUtil.Format(RemotingErrorIdStrings.CSCmdsShellNotPowerShellBased, shellName); + string shellForPowerShellCoreMsg = StringUtil.Format(RemotingErrorIdStrings.CSCmdsPowerShellCoreShellNotModifiable, shellName); + string shellForWindowsPowerShellMsg = StringUtil.Format(RemotingErrorIdStrings.CSCmdsWindowsPowerShellCoreNotModifiable, shellName); // construct object to update the properties PSObject propertiesToUpdate = ConstructPropertiesForUpdate(); @@ -3463,6 +3603,8 @@ protected override void ProcessRecord() WSManNativeApi.ResourceURIPrefix + shellName, shellNotFoundErrorMsg, shellNotPowerShellMsg, + shellForPowerShellCoreMsg, + shellForWindowsPowerShellMsg, accessModeSpecified ? AccessMode : PSSessionConfigurationAccessMode.Disabled, }); @@ -4406,7 +4548,7 @@ protected override void EndProcessing() // if user did not specify any shell, act on the default shell. if (_shellsToEnable.Count == 0) { - _shellsToEnable.Add(RemotingConstants.DefaultShellName); + _shellsToEnable.Add(PSSessionConfigurationCommandUtilities.GetWinrmPluginShellName()); } WriteVerbose(StringUtil.Format(RemotingErrorIdStrings.EcsScriptMessageV, enablePluginSbFormat)); @@ -4645,7 +4787,7 @@ protected override void EndProcessing() // if user did not specify any shell, act on the default shell. if (_shellsToDisable.Count == 0) { - _shellsToDisable.Add(RemotingConstants.DefaultShellName); + _shellsToDisable.Add(PSSessionConfigurationCommandUtilities.GetWinrmPluginShellName()); } //WriteWarning(StringUtil.Format(RemotingErrorIdStrings.DcsWarningMessage)); @@ -4704,10 +4846,8 @@ protected override void EndProcessing() /// /// /// -#if !CORECLR [Cmdlet(VerbsLifecycle.Enable, RemotingConstants.PSRemotingNoun, SupportsShouldProcess = true, ConfirmImpact = ConfirmImpact.Medium, HelpUri = "https://go.microsoft.com/fwlink/?LinkID=144300")] -#endif public sealed class EnablePSRemotingCommand : PSCmdlet { #region Private Data @@ -4718,6 +4858,18 @@ public sealed class EnablePSRemotingCommand : PSCmdlet //TODO: CLR4: Remove the logic for setting the MaxMemoryPerShellMB to 200 MB once IPMO->Get-Command->Get-Help memory usage issue is fixed. private const string enableRemotingSbFormat = @" +function Generate-PluginConfigFile +{{ +param( + [Parameter()] [string] $pluginInstallPath +) + $pluginConfigFile = Join-Path $pluginInstallPath ""RemotePowerShellConfig.txt"" + + # This always overwrites the file with a new version of it (if it already exists) + Set-Content -Path $pluginConfigFile -Value ""PSHOMEDIR=$PSHOME"" + Add-Content -Path $pluginConfigFile -Value ""CORECLRDIR=$PSHOME"" +}} + function Enable-PSRemoting {{ [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact=""Medium"")] @@ -4727,7 +4879,8 @@ function Enable-PSRemoting [Parameter()] [string] $captionForRegisterDefault, [Parameter()] [string] $queryForSet, [Parameter()] [string] $captionForSet, - [Parameter()] [bool] $skipNetworkProfileCheck + [Parameter()] [bool] $skipNetworkProfileCheck, + [Parameter()] [string] $errorMsgUnableToInstallPlugin ) end @@ -4738,16 +4891,23 @@ function Enable-PSRemoting $null = $PSBoundParameters.Remove(""captionForRegisterDefault"") $null = $PSBoundParameters.Remove(""queryForSet"") $null = $PSBoundParameters.Remove(""captionForSet"") + $null = $PSBoundParameters.Remove(""errorMsgUnableToInstallPlugin"") $PSBoundParameters.Add(""Name"",""*"") # first try to enable all the sessions Enable-PSSessionConfiguration @PSBoundParameters - # make sure default powershell end points exist - # ie., Microsoft.PowerShell - # and Microsoft.PowerShell32 (wow64) - + # + # This cmdlet will make sure default powershell end points exist upon successful completion. + # + # Windows PowerShell: + # Microsoft.PowerShell + # Microsoft.PowerShell32 (wow64) + # + # PowerShell Core: + # PowerShell. + # $errorCount = $error.Count $endPoint = Get-PSSessionConfiguration {0} -Force:$Force -ErrorAction silentlycontinue 2>&1 $newErrorCount = $error.Count @@ -4762,47 +4922,60 @@ function Enable-PSRemoting if ((!$endpoint) -and ($force -or $pscmdlet.ShouldProcess($qMessage, $captionForRegisterDefault))) {{ - $null = Register-PSSessionConfiguration {0} -force + # Create the default endpoint for the appropriate environment + if ([System.Management.Automation.Platform]::IsPowerShellCore) + {{ + $resolvedPluginInstallPath = """" + # + # Section 1: + # Move pwrshplugin.dll from $PSHOME to the endpoint directory + # + $pluginInstallPath = Join-Path ""$env:WINDIR\System32\PowerShell"" $psversiontable.GitCommitId + if (!(Test-Path $pluginInstallPath)) + {{ + $resolvedPluginInstallPath = New-Item -Type Directory -Path $pluginInstallPath + }} + else + {{ + $resolvedPluginInstallPath = Resolve-Path $pluginInstallPath + }} + if (!(Test-Path $resolvedPluginInstallPath\{5})) + {{ + Copy-Item $PSHOME\{5} $resolvedPluginInstallPath -Force + if (!(Test-Path $resolvedPluginInstallPath\{5})) + {{ + Write-Error ($errorMsgUnableToInstallPlugin -f ""{5}"", $resolvedPluginInstallPath) + return + }} + }} + + # + # Section 2: + # Generate the Plugin Configuration File + # + Generate-PluginConfigFile $resolvedPluginInstallPath + + # + # Section 3: + # Register the endpoint + # + $null = Register-PSSessionConfiguration -Name {0} -force + }} + else + {{ + $null = Register-PSSessionConfiguration {0} -force + }} set-item -WarningAction SilentlyContinue wsman:\localhost\plugin\{0}\Quotas\MaxShellsPerUser -value ""25"" -confirm:$false set-item -WarningAction SilentlyContinue wsman:\localhost\plugin\{0}\Quotas\MaxIdleTimeoutms -value {4} -confirm:$false restart-service winrm -confirm:$false }} - # Check Microsoft.PowerShell.Workflow endpoint - $errorCount = $error.Count - $endPoint = Get-PSSessionConfiguration {0}.workflow -Force:$Force -ErrorAction silentlycontinue 2>&1 - $newErrorCount = $error.Count - - # remove the 'No Session Configuration matches criteria' errors - for ($index = 0; $index -lt ($newErrorCount - $errorCount); $index ++) - {{ - $error.RemoveAt(0) - }} - - if (!$endpoint) - {{ - $qMessage = $queryForRegisterDefault -f ""Microsoft.PowerShell.Workflow"",""Register-PSSessionConfiguration Microsoft.PowerShell.Workflow -force"" - if ($force -or $pscmdlet.ShouldProcess($qMessage, $captionForRegisterDefault)) {{ - $tempxmlfile = [io.path]::Gettempfilename() - ""{1}"" | out-file -force -filepath $tempxmlfile -confirm:$false - $null = winrm create winrm/config/plugin?Name=Microsoft.PowerShell.Workflow -file:$tempxmlfile - remove-item -path $tempxmlfile -force -confirm:$false - restart-service winrm -confirm:$false - }} - }} - - $pa = $env:PROCESSOR_ARCHITECTURE - if ($pa -eq ""x86"") - {{ - # on 64-bit platforms, wow64 bit process has the correct architecture - # available in processor_architew6432 variable - $pa = $env:PROCESSOR_ARCHITEW6432 - }} - if ((($pa -eq ""amd64"")) -and (test-path $env:windir\syswow64\pwrshplugin.dll)) + # PowerShell Workflow and WOW are not supported for PowerShell Core + if (![System.Management.Automation.Platform]::IsCoreCLR) {{ - # Check availability of WOW64 endpoint. Register if not available. + # Check Microsoft.PowerShell.Workflow endpoint $errorCount = $error.Count - $endPoint = Get-PSSessionConfiguration {0}32 -Force:$Force -ErrorAction silentlycontinue 2>&1 + $endPoint = Get-PSSessionConfiguration {0}.workflow -Force:$Force -ErrorAction silentlycontinue 2>&1 $newErrorCount = $error.Count # remove the 'No Session Configuration matches criteria' errors @@ -4811,17 +4984,50 @@ function Enable-PSRemoting $error.RemoveAt(0) }} - $qMessage = $queryForRegisterDefault -f ""{0}32"",""Register-PSSessionConfiguration {0}32 -processorarchitecture x86 -force"" - if ((!$endpoint) -and - ($force -or $pscmdlet.ShouldProcess($qMessage, $captionForRegisterDefault))) + if (!$endpoint) {{ - $null = Register-PSSessionConfiguration {0}32 -processorarchitecture x86 -force - set-item -WarningAction SilentlyContinue wsman:\localhost\plugin\{0}32\Quotas\MaxShellsPerUser -value ""25"" -confirm:$false - set-item -WarningAction SilentlyContinue wsman:\localhost\plugin\{0}32\Quotas\MaxIdleTimeoutms -value {4} -confirm:$false - restart-service winrm -confirm:$false + $qMessage = $queryForRegisterDefault -f ""Microsoft.PowerShell.Workflow"",""Register-PSSessionConfiguration Microsoft.PowerShell.Workflow -force"" + if ($force -or $pscmdlet.ShouldProcess($qMessage, $captionForRegisterDefault)) {{ + $tempxmlfile = [io.path]::Gettempfilename() + ""{1}"" | out-file -force -filepath $tempxmlfile -confirm:$false + $null = winrm create winrm/config/plugin?Name=Microsoft.PowerShell.Workflow -file:$tempxmlfile + remove-item -path $tempxmlfile -force -confirm:$false + restart-service winrm -confirm:$false + }} }} - }} + $pa = $env:PROCESSOR_ARCHITECTURE + if ($pa -eq ""x86"") + {{ + # on 64-bit platforms, wow64 bit process has the correct architecture + # available in processor_architew6432 variable + $pa = $env:PROCESSOR_ARCHITEW6432 + }} + if ((($pa -eq ""amd64"")) -and (test-path $env:windir\syswow64\pwrshplugin.dll)) + {{ + # Check availability of WOW64 endpoint. Register if not available. + $errorCount = $error.Count + $endPoint = Get-PSSessionConfiguration {0}32 -Force:$Force -ErrorAction silentlycontinue 2>&1 + $newErrorCount = $error.Count + + # remove the 'No Session Configuration matches criteria' errors + for ($index = 0; $index -lt ($newErrorCount - $errorCount); $index ++) + {{ + $error.RemoveAt(0) + }} + + $qMessage = $queryForRegisterDefault -f ""{0}32"",""Register-PSSessionConfiguration {0}32 -processorarchitecture x86 -force"" + if ((!$endpoint) -and + ($force -or $pscmdlet.ShouldProcess($qMessage, $captionForRegisterDefault))) + {{ + $null = Register-PSSessionConfiguration {0}32 -processorarchitecture x86 -force + set-item -WarningAction SilentlyContinue wsman:\localhost\plugin\{0}32\Quotas\MaxShellsPerUser -value ""25"" -confirm:$false + set-item -WarningAction SilentlyContinue wsman:\localhost\plugin\{0}32\Quotas\MaxIdleTimeoutms -value {4} -confirm:$false + restart-service winrm -confirm:$false + }} + }} + }} + # remove the 'network deny all' tag Get-PSSessionConfiguration -Force:$Force | ForEach-Object {{ $sddl = $null @@ -4888,7 +5094,7 @@ function Enable-PSRemoting }} # end of end block }} # end of Enable-PSRemoting -Enable-PSRemoting -force $args[0] -queryForRegisterDefault $args[1] -captionForRegisterDefault $args[2] -queryForSet $args[3] -captionForSet $args[4] -whatif:$args[5] -confirm:$args[6] -skipNetworkProfileCheck $args[7] +Enable-PSRemoting -force $args[0] -queryForRegisterDefault $args[1] -captionForRegisterDefault $args[2] -queryForSet $args[3] -captionForSet $args[4] -whatif:$args[5] -confirm:$args[6] -skipNetworkProfileCheck $args[7] -errorMsgUnableToInstallPlugin $args[8] "; private const string _workflowConfigXml = @" @@ -4942,11 +5148,11 @@ static EnablePSRemotingCommand() PSSessionConfigurationCommandBase.GetLocalSddl()); string enableRemotingScript = string.Format(CultureInfo.InvariantCulture, - enableRemotingSbFormat, RemotingConstants.DefaultShellName, + enableRemotingSbFormat, PSSessionConfigurationCommandUtilities.GetWinrmPluginShellName(), // Workflow endpoint configuration will be done through Register-PSSessionConfiguration // when the new features are available. workflowConfigXml, PSSessionConfigurationCommandBase.RemoteManagementUsersSID, PSSessionConfigurationCommandBase.InteractiveUsersSID, - RemotingConstants.MaxIdleTimeoutMS); + RemotingConstants.MaxIdleTimeoutMS, RemotingConstants.PSPluginDLLName); // compile the script block statically and reuse the same instance // everytime the command is run..This will save on parsing time. @@ -5039,7 +5245,8 @@ protected override void EndProcessing() setCaptionMessage, whatIf, confirm, - _skipNetworkProfileCheck}); + _skipNetworkProfileCheck, + RemotingErrorIdStrings.UnableToInstallPlugin}); } #endregion @@ -5054,10 +5261,8 @@ protected override void EndProcessing() /// Only disable the network access to the Session Configuration. The /// local access is still enabled /// -#if !CORECLR [Cmdlet(VerbsLifecycle.Disable, RemotingConstants.PSRemotingNoun, SupportsShouldProcess = true, ConfirmImpact = ConfirmImpact.Medium, HelpUri = "https://go.microsoft.com/fwlink/?LinkID=144298")] -#endif public sealed class DisablePSRemotingCommand : PSCmdlet { # region Private Data diff --git a/src/System.Management.Automation/resources/RemotingErrorIdStrings.resx b/src/System.Management.Automation/resources/RemotingErrorIdStrings.resx index 5f9f5a98ed5..97e2247985c 100644 --- a/src/System.Management.Automation/resources/RemotingErrorIdStrings.resx +++ b/src/System.Management.Automation/resources/RemotingErrorIdStrings.resx @@ -655,6 +655,12 @@ Session configuration "{0}" is not a Windows PowerShell-based shell. + + + Session configuration "{0}" is a PowerShell Core-based shell. Please use PowerShell Core to modify it. + + + Session configuration "{0}" is a Windows PowerShell-based shell. Please use Windows PowerShell to modify it. No session configuration matches criteria "{0}". @@ -1638,6 +1644,14 @@ All WinRM sessions connected to Windows PowerShell session configurations, such The SSH transport process has abruptly terminated causing this remote session to break. + + PowerShell Core does not support WOW64. The binary must match the architecture of the processor. + + + Unable to install plugin {0} to directory {1}. + + + The WinRM plugin DLL {0} is missing for PowerShell Core. Please run Enable-PSRemoting and then retry this command. This parameter set requires WSMan, and no supported WSMan client library was found. WSMan is either not installed or unavailable for this system. From b13ba33b63636bd977a282635fafaffdac73c575 Mon Sep 17 00:00:00 2001 From: PowerShell Team Date: Tue, 8 Nov 2016 10:56:54 -0800 Subject: [PATCH 02/12] Porting PSSessionConfigurationTests to GitHub --- .../PSSessionConfiguration.Tests.ps1 | 874 ++++++++++++++++++ 1 file changed, 874 insertions(+) create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 new file mode 100644 index 00000000000..f25a203c5b0 --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 @@ -0,0 +1,874 @@ + +try { + #skip all tests on non-windows platform + $originalDefaultParameterValues = $PSDefaultParameterValues.Clone() + $IsNotSkipped = $IsWindows + $PSDefaultParameterValues["it:skip"] = !$IsNotSkipped + + # + # Tests whether PowerShell remoting is enabled for this instance of PowerShell. + # If remoting is not enabled, it will enable it and then clean up after all the tests + # have executed. + # + if ($IsNotSkipped) + { + Import-Module (join-path $psscriptroot "../../Common/Test.Helpers.psm1") + + $endpointCreated = $false + $endpointName = "microsoft.powershell" + + if (($IsCoreCLR) -AND (Test-IsElevated)) + { + $endpointName = "PowerShell.$($psversiontable.GitCommitId)" + + # Throws a "No session configuration matches criteria $endpointName" WriteErrorException if no endpoint is found + $matchedEndpoint = Get-PSSessionConfiguration $endpointName -ErrorAction SilentlyContinue + + if ($matchedEndpoint -eq $null) + { + # An endpoint for this instance of PowerShell does not exist. + # + # -SkipNetworkProfileCheck is used in case Docker or another application + # has created a publich virtual network profile on the system + Enable-PSRemoting -SkipNetworkProfileCheck + $endpointCreated = $true + } + } + } + + try + { + Describe "Validate Register-PSSessionConfiguration" -Tags @("CI", 'RequireAdminOnWindows') { + + AfterAll { + if ($IsNotSkipped) + { + Get-PSSessionConfiguration -Name "ITTask*" -ErrorAction SilentlyContinue | Unregister-PSSessionConfiguration + } + } + + It "Register-PSSessionConfiguration -TransportOption" { + + $ConfigurationName = "ITTask" + (Get-Random -Minimum 10000 -Maximum 99999) + $Transport = New-PSTransportOption -MaxSessions 40 -IdleTimeoutSec 3600 + + $null = Register-PSSessionConfiguration -Name $ConfigurationName -TransportOption $Transport + $result = Get-PSSessionConfiguration -Name $ConfigurationName + + $result.MaxShells | Should Be 40 + $result.IdleTimeoutms | Should Be 3600000 + } + } + Describe "Validate Get-PSSessionConfiguration, Enable-PSSessionConfiguration, Disable-PSSessionConfiguration, Unregister-PSSessionConfiguration cmdlets" -Tags @("CI", 'RequireAdminOnWindows') { + + BeforeAll { + if ($IsNotSkipped) + { + # Register new session configuration + function RegisterNewConfiguration { + param ( + + [string] + $Name, + + [string] + $ConfigFilePath, + + [switch] + $Enabled + ) + + $TestConfig = Get-PSSessionConfiguration -Name $Name -ErrorAction SilentlyContinue + if($TestConfig) + { + $null = Unregister-PSSessionConfiguration -Name $Name + } + + if($Enabled) + { + $null = Register-PSSessionConfiguration -Name $Name -Path $ConfigFilePath + } + else + { + $null = Register-PSSessionConfiguration -Name $Name -Path $ConfigFilePath -AccessMode Disabled + } + } + + # Unregister session configuration + function UnregisterPSSessionConfiguration{ + param ( + + [string] + $Name + ) + + Unregister-PSSessionConfiguration -Name $Name -Force -NoServiceRestart -ErrorAction SilentlyContinue + } + + # Create new Config File + function CreateTestConfigFile { + + $TestConfigFileLoc = join-path $env:SystemDrive "MultiMachineTestData\Remoting\cmdlets" + if(-not (Test-path $TestConfigFileLoc)) + { + $null = New-Item -Path $TestConfigFileLoc -ItemType Directory -Force -ErrorAction Stop + } + + $TestConfigFile = join-path $TestConfigFileLoc "TestConfigFile.pssc" + $null = New-PSSessionConfigurationFile -Path $TestConfigFile -SessionType Default + + return $TestConfigFile + } + + $LocalConfigFilePath = CreateTestConfigFile + } + } + + Context "Validate Get-PSSessionConfiguration cmdlet" { + + It "Get-PSSessionConfiguration with no parameter" { + + $Result = Get-PSSessionConfiguration + + $Result.Name -contains $endpointName | Should Be $true + $Result.PSVersion -ge 5.1 | Should be $true + } + + It "Get-PSSessionConfiguration with Name parameter" { + + $Result = Get-PSSessionConfiguration -Name $endpointName + + $Result.Name | Should Be $endpointName + $Result.PSVersion -ge 5.1 | Should be $true + } + + It "Get-PSSessionConfiguration -Name with wildcard character" { + + $endpointWildcard = "microsoft*" + if ($IsCoreCLR) + { + $endpointWildcard = "powershell.*" + } + + $Result = Get-PSSessionConfiguration -Name $endpointWildcard + + $Result.Name -contains $endpointName | Should Be $true + $Result.PSVersion -ge 5.1 | Should be $true + } + + It "Get-PSSessionConfiguration -Name with Non-Existent session configuration" { + + try + { + Get-PSSessionConfiguration -Name "NonExistantSessionConfiguration" -ErrorAction Stop + throw "No Exception!" + } + catch + { + $_.FullyQualifiedErrorId | Should Be "Microsoft.PowerShell.Commands.WriteErrorException" + } + } + } + + Context "Validate Enable-PSSessionConfiguration and Disable-PSSessionConfiguration" { + + function VerifyEnableAndDisablePSSessionConfig { + param ( + [string] + $SessionConfigName, + + [string] + $ConfigFilePath, + + [Bool] + $InitialSessionStateEnabled, + + [Bool] + $FinalSessionStateEnabled, + + [string] + $TestDescription, + + [bool] + $EnablePSSessionConfig + ) + + It "$TestDescription" { + + RegisterNewConfiguration -Name $SessionConfigName -ConfigFilePath $ConfigFilePath -Enabled:$InitialSessionStateEnabled + + $TestConfigStateBeforeChange = (Get-PSSessionConfiguration -Name $SessionConfigName).Enabled + + if($EnablePSSessionConfig) + { + $isSkipNetworkCheck = $true + # TODO: Get-NetConnectionProfile is not available during typical PS Core deployments. Once it is, this check should be used. + #Get-NetConnectionProfile | Where-Object { $_.NetworkCategory -eq "Public" } | ForEach-Object { $isSkipNetworkCheck = $true } + Enable-PSSessionConfiguration -Name $SessionConfigName -NoServiceRestart -SkipNetworkProfileCheck:$isSkipNetworkCheck + } + else + { + Disable-PSSessionConfiguration -Name $SessionConfigName -NoServiceRestart + } + + $TestConfigStateAfterChange = (Get-PSSessionConfiguration -Name $SessionConfigName -ErrorAction SilentlyContinue).Enabled + + UnregisterPSSessionConfiguration -Name $SessionConfigName + + $TestConfigStateBeforeChange | Should be "$InitialSessionStateEnabled" + $TestConfigStateAfterChange | Should be "$FinalSessionStateEnabled" + } + } + + $TestData = @( + @{ + SessionConfigName = "TestDisablePSSessionConfig" + ConfigFilePath = $LocalConfigFilePath + InitialSessionStateEnabled = $true + FinalSessionStateEnabled = $false + TestDescription = "Validate Disable-Configuration cmdlet" + EnablePSSessionConfig = $false + } + + @{ + SessionConfigName = "TestEnablePSSessionConfig" + ConfigFilePath = $LocalConfigFilePath + InitialSessionStateEnabled = $false + FinalSessionStateEnabled = $true + TestDescription = "Validate Enable-Configuration cmdlet" + EnablePSSessionConfig = $true + } + ) + + foreach ($testcase in $testData) + { + VerifyEnableAndDisablePSSessionConfig @testcase + } + } + + Context "Validate Unregister-PSSessionConfiguration cmdlet" { + + BeforeEach { + Register-PSSessionConfiguration -Name "TestUnregisterPSSessionConfig" + } + + AfterAll { + if ($IsNotSkipped) + { + Unregister-PSSessionConfiguration -name "TestUnregisterPSSessionConfig" -ErrorAction SilentlyContinue | Out-Null + } + } + + function TestUnRegisterPSSsessionConfiguration { + + param ($Description, $SessionConfigName, $ExpectedOutput, $ExpectedError) + + It "$Description" { + + $Result = [PSObject] @{Output = $true ; Error = $null} + $Error.Clear() + try + { + $null = Unregister-PSSessionConfiguration -name $SessionConfigName -ErrorAction stop + } + catch + { + $Result.Error = $_.Exception + } + + if(-not $Result.Error) + { + $ValidEndpoints = [PSObject]@(Get-PSSessionConfiguration) + + foreach ($endpoint in $ValidEndpoints) + { + # Setting it to false means the unregister was unsuccessful + # and there is still an endpoint with name matching the one we wanted to remove. + if($endpoint.name -like $SessionConfigName) + { + $Result.Output = $false + break + } + } + } + else + { + $Result.Output = $false + } + + $Result.Output | Should Match $ExpectedOutput + $Result.Error | Should Match $ExpectedError + } + } + + $TestData = @( + @{ + Description = "Validate Unregister-PSSessionConfiguration with -name parameter" + SessionConfigName = "TestUnregisterPSSessionConfig" + ExpectedOutput = $true + ExpectedError = $null + } + @{ + Description = "Validate Unregister-PSSessionConfiguration with name having wildcard character" + SessionConfigName = "TestUnregister*" + ExpectedOutput = $true + ExpectedError = $null + } + @{ + Description = "Validate Unregister-PSSessionConfiguration for non-existant endpoint" + SessionConfigName = 'TestInvalidEndPoint' + ExpectedOutput = $false + ExpectedError = "No session configuration matches criteria `"TestInvalidEndPoint`"." + } + ) + + foreach ($TestCase in $TestData) + { + TestUnRegisterPSSsessionConfiguration @TestCase + } + } + } + + Describe "Validate Register-PSSessionConfiguration, Set-PSSessionConfiguration cmdlets" -Tags @("Feature", 'RequireAdminOnWindows') { + + BeforeAll { + if ($IsNotSkipped) + { + function ValidateRemoteEndpoint { + param ($TestSessionConfigName, $ScriptToExecute, $ExpectedOutput) + + $Result = [PSObject]@{Output= $null; Error = $null} + try + { + $sn = New-PSSession . -ConfigurationName $TestSessionConfigName -ErrorAction Stop + if($sn) + { + if($ScriptToExecute) + { + $Result.Output = invoke-command -Session $Sn -ScriptBlock { param ($scripttoExecute) Invoke-Expression $scripttoExecute} -ArgumentList $ScriptToExecute + } + else + { + $Result.Output = $true + } + } + else + { + throw "Unable to create session $TestSessionConfigName" + } + } + catch + { + $Result.Error = $_.Error.FullyQualifiedErrorId + } + finally + { + if ($sn) + { + Remove-PSSession $sn -ErrorAction SilentlyContinue | Out-Null + $sn = $null + } + } + $Result.Output | Should be $ExpectedOutput + $Result.Error | Should be $null + } + + # Create Test Startup Script + function CreateStartupScript { + $ScriptContent = @" +`$global:testvariable = "testValue" +"@ + + $TestScript = join-path $global:TestDir "StartupTestScript.ps1" + $null = Set-Content -path $TestScript -Value $ScriptContent + + return $TestScript + } + + # Create new Config File + function CreateTestConfigFile { + + $TestConfigFile = join-path $global:TestDir "TestConfigFile.pssc" + $null = New-PSSessionConfigurationFile -Path $TestConfigFile -SessionType Default + return $TestConfigFile + } + + function CreateTestModule { + $ScriptContent = @" +function IsTestModuleImported { +return `$true +} +Export-ModuleMember IsTestModuleImported +"@ + $TestModuleFileLoc = $global:TestDir + + if(-not (Test-path $TestModuleFileLoc)) + { + $null = New-Item -Path $TestModuleFileLoc -ItemType Directory -Force -ErrorAction Stop + } + + $TestModuleFile = join-path $TestModuleFileLoc "TestModule.psm1" + $null = Set-Content -path $TestModuleFile -Value $ScriptContent + + return $TestModuleFile + } + + function CreateTestAssembly { + $PscConfigDef = @" +using System; +using System.Management.Automation; +using System.Management.Automation.Runspaces; +using System.Management.Automation.Remoting; + +namespace PowershellTestConfigNamespace +{ + public sealed class PowershellTestConfig : PSSessionConfiguration + { + /// + /// + /// + /// + /// + public override InitialSessionState GetInitialSessionState(PSSenderInfo senderInfo) + { + return InitialSessionState.CreateDefault(); + } + + } +} +"@ + $global:Sma = [reflection.assembly]::load('System.Management.Automation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL').location + $global:SourceFile = join-path $global:TestDir "PowershellTestConfig.cs" + $PscConfigDef | out-file $global:SourceFile -Encoding ascii -Force + $TestAssemblyName = "TestAssembly.dll" + $TestAssemblyPath = join-path $global:TestDir $TestAssemblyName + Add-Type -path $global:SourceFile -ReferencedAssemblies $global:Sma -OutputAssembly $TestAssemblyPath + return $TestAssemblyName + } + + $global:TestDir = join-path $env:SystemDrive "MultiMachineTestData\Remoting\cmdlets" + if(-not (Test-Path $global:TestDir)) + { + $null = New-Item -path $global:TestDir -ItemType Directory + } + + $LocalConfigFilePath = CreateTestConfigFile + $LocalStartupScriptPath = CreateStartupScript + $LocalTestModulePath = CreateTestModule + $LocalTestAssemblyName = CreateTestAssembly + $LocalTestDir = $global:TestDir + } + } + + AfterAll { + if ($IsNotSkipped) + { + Remove-Item $LocalTestDir -Recurse -Force -ErrorAction SilentlyContinue + } + } + + Context "Validate Register-PSSessionConfiguration" { + + BeforeAll { + if ($IsNotSkipped) + { + $TestSessionConfigName = "TestRegisterPSSesionConfig" + Unregister-PSSessionConfiguration -Name $TestSessionConfigName -Force -NoServiceRestart -ErrorAction SilentlyContinue + } + } + + AfterEach { + #Unregister-PSSessionConfiguration -Name $TestSessionConfigName -Force -NoServiceRestart -ErrorAction SilentlyContinue + } + + It "Validate Register-PSSessionConfiguration -name -path" { + + $pssessionthreadoptions = "UseCurrentThread" + $psmaximumreceivedobjectsizemb = 20 + $psmaximumreceiveddatasizepercommandmb = 20 + $UseSharedProcess = $true + + Register-PSSessionConfiguration -Name $TestSessionConfigName -path $LocalConfigFilePath -MaximumReceivedObjectSizeMB $psmaximumreceivedobjectsizemb -MaximumReceivedDataSizePerCommandMB $psmaximumreceiveddatasizepercommandmb -UseSharedProcess:$UseSharedProcess -ThreadOptions $pssessionthreadoptions + $Result = [PSObject]@{Session = Get-PSSessionConfiguration -Name $TestSessionConfigName; Culture = (Get-Item WSMan:\localhost\Plugin\$endpointName\lang -ea SilentlyContinue).value} + + $Result.Session.Name | Should be $TestSessionConfigName + $Result.Session.SessionType | Should be "Default" + $Result.Session.PSVersion | Should be 6.0 + $Result.Session.Enabled | Should be $true + $Result.Session.lang | Should be $Result.Culture + $Result.Session.pssessionthreadoptions | Should be $pssessionthreadoptions + $Result.Session.psmaximumreceivedobjectsizemb | Should be $psmaximumreceivedobjectsizemb + $Result.Session.psmaximumreceiveddatasizepercommandmb | Should be $psmaximumreceiveddatasizepercommandmb + $Result.Session.UseSharedProcess | Should be $UseSharedProcess + } + + It "Validate Register-PSSessionConfiguration -startupscript parameter" { + + $null = Register-PSSessionConfiguration -Name $TestSessionConfigName -path $LocalConfigFilePath -StartupScript $LocalStartupScriptPath -Force + + ValidateRemoteEndpoint -TestSessionConfigName $TestSessionConfigName -ScriptToExecute "return `$global:testvariable" -ExpectedOutput "testValue" -ExpectedError $null + } + + + It "Validate Register-PSSessionConfiguration -AccessMode parameter" { + + $null = Register-PSSessionConfiguration -Name $TestSessionConfigName -path $LocalConfigFilePath -AccessMode Disabled -Force + + ValidateRemoteEndpoint -TestSessionConfigName $TestSessionConfigName -ScriptToExecute $null -ExpectedOutput $null -ExpectedError "RemoteConnectionDisallowed,PSSessionOpenFailed" + } + + + It "Validate Register-PSSessionConfiguration -ModulesToImport parameter" { + + $null = Register-PSSessionConfiguration -Name $TestSessionConfigName -ModulesToImport $LocalTestModulePath -Force + + ValidateRemoteEndpoint -TestSessionConfigName $TestSessionConfigName -ScriptToExecute "return IsTestModuleImported" -ExpectedOutput $true -ExpectedError $null + } + + It "Validate Register-PSSessionConfiguration with ApplicationBase , AssemblyName and ConfigurationTypeName parameter" { + + $TestAssemblyPath = join-path $LocalTestDir $LocalTestAssemblyName + add-type -path $global:SourceFile -ReferencedAssemblies $global:Sma -OutputAssembly $TestAssemblyPath + $null = Register-PSSessionConfiguration -Name $TestSessionConfigName -ApplicationBase $LocalTestDir -AssemblyName $LocalTestAssemblyName -ConfigurationTypeName "PowershellTestConfigNamespace.PowershellTestConfig" -force + + ValidateRemoteEndpoint -TestSessionConfigName $TestSessionConfigName -ScriptToExecute $null -ExpectedOutput $true -ExpectedError $null + } + } + + Context "Validate Set-PSSessionConfiguration" { + + BeforeAll { + if ($IsNotSkipped) + { + $TestSessionConfigName = "TestSetPSSesionConfig" + Unregister-PSSessionConfiguration -Name $TestSessionConfigName -Force -NoServiceRestart -ErrorAction SilentlyContinue + } + } + + AfterEach { + Unregister-PSSessionConfiguration -Name $TestSessionConfigName -Force -NoServiceRestart -ErrorAction SilentlyContinue + } + + BeforeEach { + Register-PSSessionConfiguration -Name $TestSessionConfigName + } + + It "Validate Set-PSSessionConfiguration -name -path -MaximumReceivedObjectSizeMB -MaximumReceivedDataSizePerCommandMB -UseSharedProcess -ThreadOptions parameters" { + + $pssessionthreadoptions = "UseCurrentThread" + $psmaximumreceivedobjectsizemb = 20 + $psmaximumreceiveddatasizepercommandmb = 20 + $UseSharedProcess = $true + + Set-PSSessionConfiguration -Name $TestSessionConfigName -MaximumReceivedObjectSizeMB $psmaximumreceivedobjectsizemb -MaximumReceivedDataSizePerCommandMB $psmaximumreceiveddatasizepercommandmb -UseSharedProcess:$UseSharedProcess -ThreadOptions $pssessionthreadoptions -NoServiceRestart + $Result = [PSObject]@{Session = (Get-PSSessionConfiguration -Name $TestSessionConfigName) ; Culture = (Get-Item WSMan:\localhost\Plugin\microsoft.powershell\lang -ea SilentlyContinue).value} + + $Result.Session.Name | Should be $TestSessionConfigName + $Result.Session.PSVersion | Should be 6.0 + $Result.Session.Enabled | Should be $true + $Result.Session.lang | Should be $result.Culture + $Result.Session.pssessionthreadoptions | Should be $pssessionthreadoptions + $Result.Session.psmaximumreceivedobjectsizemb | Should be $psmaximumreceivedobjectsizemb + $Result.Session.psmaximumreceiveddatasizepercommandmb | Should be $psmaximumreceiveddatasizepercommandmb + $Result.Session.UseSharedProcess | Should be $UseSharedProcess + } + + It "Validate Set-PSSessionConfiguration -startupscript parameter" { + + $null = Set-PSSessionConfiguration -Name $TestSessionConfigName -StartupScript $LocalStartupScriptPath + + ValidateRemoteEndpoint -TestSessionConfigName $TestSessionConfigName -ScriptToExecute "return `$global:testvariable" -ExpectedOutput "testValue" -ExpectedError $null + } + + It "Validate Set-PSSessionConfiguration -AccessMode parameter" { + + $null = Set-PSSessionConfiguration -Name $TestSessionConfigName -AccessMode Disabled + + ValidateRemoteEndpoint -TestSessionConfigName $TestSessionConfigName -ScriptToExecute $null -ExpectedOutput $null -ExpectedError "RemoteConnectionDisallowed,PSSessionOpenFailed" + } + + It "Validate Set-PSSessionConfiguration -ModulesToImport parameter" { + + $null = Set-PSSessionConfiguration -Name $TestSessionConfigName -ModulesToImport $LocalTestModulePath -Force + + ValidateRemoteEndpoint -TestSessionConfigName $TestSessionConfigName -ScriptToExecute "return IsTestModuleImported" -ExpectedOutput $true -ExpectedError $null + } + + It "Validate Set-PSSessionConfiguration with ApplicationBase , AssemblyName and ConfigurationTypeName parameter" { + + $TestAssemblyPath = join-path $LocalTestDir $LocalTestAssemblyName + Add-type -path $global:SourceFile -ReferencedAssemblies $global:Sma -OutputAssembly $TestAssemblyPath + $null = Register-PSSessionConfiguration -Name $TestSessionConfigName -ApplicationBase $LocalTestDir -AssemblyName $LocalTestAssemblyName -ConfigurationTypeName "PowershellTestConfigNamespace.PowershellTestConfig" -force + + ValidateRemoteEndpoint -TestSessionConfigName $TestSessionConfigName -ScriptToExecute $null -ExpectedOutput $true -ExpectedError $null + } + } + } + } + finally + { + if ($endpointCreated) + { + Get-PSSessionConfiguration $endpointName -ErrorAction SilentlyContinue | Unregister-PSSessionConfiguration + } + } + + Describe "Basic tests for New-PSSessionConfigurationFile Cmdlet" -Tags @("CI", 'RequireAdminOnWindows') { + + It "Validate New-PSSessionConfigurationFile can successfully create a valid PSSessionConfigurationFile" { + + $configFilePath = join-path $env:SystemDrive "SamplePSSessionConfigurationFile.pssc" + try + { + New-PSSessionConfigurationFile $configFilePath + $result = get-content $configFilePath | Out-String + } + finally + { + if(Test-Path $configFilePath){ Remove-Item $configFilePath -Force } + } + + $resultContent = invoke-expression ($result) + $resultContent.GetType().ToString() | Should Be "System.Collections.Hashtable" + + # The default created hashtable in the session configuration file would have the + # following keys which we are validating below. + $resultContent.ContainsKey("SessionType") -and $resultContent.ContainsKey("SchemaVersion") -and $resultContent.ContainsKey("Guid") -and $resultContent.ContainsKey("Author") | Should Be $true + } + } + + Describe "Feature tests for New-PSSessionConfigurationFile Cmdlet" -Tags @("Feature", 'RequireAdminOnWindows') { + + It "Validate FullyQualifiedErrorId from New-PSSessionConfigurationFile when invalid path is provided as input" { + + try + { + $filePath = "cert:\foo.pssc" + New-PSSessionConfigurationFile $filePath + throw "No Exception!" + } + catch + { + $_.FullyQualifiedErrorId | Should Be "InvalidPSSessionConfigurationFilePath,Microsoft.PowerShell.Commands.NewPSSessionConfigurationFileCommand" + } + } + } + + Describe "Test suite for Test-PSSessionConfigurationFile Cmdlet" -Tags @("CI", 'RequireAdminOnWindows') { + + BeforeAll { + if ($IsNotSkipped) + { + $parmMap = @{ + # values for PSSessionConfigFile + PowerShellVersion = '3.0' + SessionType = 'Default' + Author = 'User' + CompanyName = 'Microsoft Corporation' + Copyright = 'Copyright (c) 2011 Microsoft Corporation. All rights reserved.' + Description = 'This is a sample session configuration file.' + GUID = '73cba863-aa49-4cbf-9917-269ddcf2b1e3' + SchemaVersion = '1.0.0.0' + + # The scope of the test is to validate that a valid SessionConfigurationFile can be validated + # The test does not register the session configuration from the created session configuration file. + # The SCRATCH location is not validated. + EnvironmentVariables = @{ + PSModulePath = '$Env:PSModulePath + ";$env:SystemDrive\ProgramData"'; + SCRATCH = "\\SomeValidRemoteShare\SharedLocation" + } + + # The scope of the test is to validate that a valid SessionConfigurationFile can be validated + # The test does not register the session configuration from the created session configuration file. + # The AssembliesToLoad are not loaded by this test. The Test only validates that the supplied data + # is used to create a valid Session configuration file. + AssembliesToLoad = 'SomeValidBinary.dll' + + # The same explanation as above holds good here. + ModulesToImport = 'SomeValidModule' + AliasDefinitions = @( + @{ + Name = "gh"; + Value = "Get-Help"; + Description = "Gets the help"; + Options = "AllScope"; + }, + @{ + Name = "sh"; + Value = "Save-Help"; + Description = "Saves the help"; + Options = "Private"; + }, + @{ + Name = "uh"; + Value = "Update-Help"; + Description = "Updates the help"; + Options = "ReadOnly"; + } + ) + FunctionDefinitions=@( + @{ + Name = "sysmodules"; + ScriptBlock = 'pushd $pshome\Modules'; + Options = "AllScope"; + }, + @{ + Name = "mymodules"; + ScriptBlock = 'pushd $home\Documents\WindowsPowerShell\Modules'; + Options = "ReadOnly"; + } + ) + VariableDefinitions = @( + @{ + Name = "WarningPreference"; + Value = "SilentlyContinue"; + }, + @{ + Name = "datahome"; + Value = "\\fileserver\share\data"; + }, + @{ + Name = "allusershome"; + Value = '$env:ProgramData' + } + ) + + # The scope of the test is to validate that a valid SessionConfigurationFile can be validated + # The test does not register the session configuration from the created session configuration file. + # The existance of the files supplied as input to TypesToProcess, FormatsToProcess, ScriptsToProcess + # are not validated while creating a valid session configurtation file. + # The Test only validates that the supplied data can be successfully used to create a valid Session configuration file. + TypesToProcess = '$env:SystemDrive\SampleTypesFile.ps1xml' + FormatsToProcess = '$env:SystemDrive\SampleFormatsFile.ps1xml' + ScriptsToProcess = '$env:SystemDrive\SampleScript.ps1' + VisibleAliases = "c*","g*","i*","s*" + VisibleCmdlets = "c*","get*","i*","set*" + VisibleFunctions = "*" + VisibleProviders = 'FileSystem','Function','Registry','Variable' + VisibleVariables = "*" + LanguageMode = "RestrictedLanguage" + ExecutionPolicy = "AllSigned" + } + } + } + + It "Validate FullyQualifiedErrorId from Test-PSSessionConfigurationFile when invalid path is provided as input" { + + try + { + Test-PSSessionConfigurationFile "cert:\foo.pssc" -ErrorAction Stop + throw "No Exception!" + } + catch + { + $_.FullyQualifiedErrorId | Should Be "PSSessionConfigurationFileNotFound,Microsoft.PowerShell.Commands.TestPSSessionConfigurationFileCommand" + } + } + + It "Validate FullyQualifiedErrorId from Test-PSSessionConfigurationFile when an invalid pssc file is provided as input and -Verbose parameter is specified" { + + $configFilePath = join-path $env:SystemDrive "SamplePSSessionConfigurationFile.pssc" + "InvalidData" | Out-File $configFilePath + + try + { + Test-PSSessionConfigurationFile $configFilePath -Verbose -ErrorAction Stop + throw "No Exception!" + } + catch + { + $_.FullyQualifiedErrorId | Should Be "PSSessionConfigurationFileNotFound,Microsoft.PowerShell.Commands.TestPSSessionConfigurationFileCommand" + } + finally + { + if(Test-Path $configFilePath) + { + Remove-Item $configFilePath -Force + } + } + } + + It "Test case verifies that the generated config file passes validation" { + + # Path the config file + $configFilePath = join-path $env:SystemDrive "SamplePSSessionConfigurationFile.pssc" + + $updatedFunctionDefn = @() + foreach($currentDefination in $parmMap.FunctionDefinitions) + { + $createdFunctionDefn = @{} + foreach($currentDefinationKey in $currentDefination.Keys) + { + if($currentDefinationKey -eq "ScriptBlock") + { + $value = [ScriptBlock]::Create($currentDefination[$currentDefinationKey]) + } + else + { + $value = $currentDefination[$currentDefinationKey] + } + $createdFunctionDefn.Add($currentDefinationKey, $value) + } + $updatedFunctionDefn += $createdFunctionDefn + } + + $updatedVariableDefn = @() + foreach($currentDefination in $parmMap.VariableDefinitions) + { + $createdVariableDefn = @{} + foreach($currentDefinationKey in $currentDefination.Keys) + { + $createdVariableDefn.Add($currentDefinationKey, $currentDefination[$currentDefinationKey]) + } + $updatedVariableDefn += $createdVariableDefn + } + + try + { + # Create Config file + New-PSSessionConfigurationFile ` + -Path $configFilePath ` + -SchemaVersion $parmMap.SchemaVersion ` + -Author $parmMap.Author ` + -CompanyName $parmMap.CompanyName ` + -Copyright $parmMap.Copyright ` + -Description $parmMap.Description ` + -PowerShellVersion $parmMap.PowerShellVersion ` + -SessionType $parmMap.SessionType ` + -ModulesToImport $parmMap.ModulesToImport ` + -AssembliesToLoad $parmMap.AssembliesToLoad ` + -VisibleAliases $parmMap.VisibleAliases ` + -VisibleCmdlets $parmMap.VisibleCmdlets ` + -VisibleFunctions $parmMap.VisibleFunctions ` + -VisibleProviders $parmMap.VisibleProviders ` + -AliasDefinitions $parmMap.AliasDefinitions ` + -FunctionDefinitions $updatedFunctionDefn ` + -VariableDefinitions $updatedVariableDefn ` + -EnvironmentVariables $parmMap.EnvironmentVariables ` + -TypesToProcess $parmMap.TypesToProcess ` + -FormatsToProcess $parmMap.FormatsToProcess ` + -LanguageMode $parmMap.LanguageMode ` + -ExecutionPolicy $parmMap.ExecutionPolicy ` + -ScriptsToProcess $parmMap.ScriptsToProcess ` + -GUID $parmMap.GUID + + # Verify the generated config file using the Test-PSSessionConfigurationFile + $result = Test-PSSessionConfigurationFile -Path $configFilePath -Verbose + } + + finally + { + if(Test-Path $configFilePath) + { + Remove-Item $configFilePath -Force + } + } + + $result | Should Be $true + } + } +} +finally { + $global:PSDefaultParameterValues = $originalDefaultParameterValues +} + From 40031d1cde7f18a4bfb5ac260d93587c6d949b66 Mon Sep 17 00:00:00 2001 From: Paul Higinbotham Date: Wed, 26 Jul 2017 10:49:16 -0700 Subject: [PATCH 03/12] Fixes to PSSessionConfiguration tests --- .../PSSessionConfiguration.Tests.ps1 | 46 ++++++++----------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 index f25a203c5b0..4d08ec0a572 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 @@ -1,38 +1,31 @@ -try { - #skip all tests on non-windows platform +try +{ + # Skip all tests on non-windows and non-PowerShellCore and non-elevated platforms. $originalDefaultParameterValues = $PSDefaultParameterValues.Clone() - $IsNotSkipped = $IsWindows + $IsNotSkipped = ($IsWindows -and $IsCoreCLR -and (Test-IsElevated)) $PSDefaultParameterValues["it:skip"] = !$IsNotSkipped # + # TODO: Enable-PSRemoting should be performed at a higher set up for all tests. # Tests whether PowerShell remoting is enabled for this instance of PowerShell. # If remoting is not enabled, it will enable it and then clean up after all the tests # have executed. # if ($IsNotSkipped) { - Import-Module (join-path $psscriptroot "../../Common/Test.Helpers.psm1") + $endpointName = "PowerShell.$($psversiontable.GitCommitId)" - $endpointCreated = $false - $endpointName = "microsoft.powershell" + $matchedEndpoint = Get-PSSessionConfiguration $endpointName -ErrorAction SilentlyContinue - if (($IsCoreCLR) -AND (Test-IsElevated)) + if ($matchedEndpoint -eq $null) { - $endpointName = "PowerShell.$($psversiontable.GitCommitId)" - - # Throws a "No session configuration matches criteria $endpointName" WriteErrorException if no endpoint is found - $matchedEndpoint = Get-PSSessionConfiguration $endpointName -ErrorAction SilentlyContinue - - if ($matchedEndpoint -eq $null) - { - # An endpoint for this instance of PowerShell does not exist. - # - # -SkipNetworkProfileCheck is used in case Docker or another application - # has created a publich virtual network profile on the system - Enable-PSRemoting -SkipNetworkProfileCheck - $endpointCreated = $true - } + # An endpoint for this instance of PowerShell does not exist. + # + # -SkipNetworkProfileCheck is used in case Docker or another application + # has created a publich virtual network profile on the system + Enable-PSRemoting -SkipNetworkProfileCheck + $endpointCreated = $true } } @@ -144,11 +137,7 @@ try { It "Get-PSSessionConfiguration -Name with wildcard character" { - $endpointWildcard = "microsoft*" - if ($IsCoreCLR) - { - $endpointWildcard = "powershell.*" - } + $endpointWildcard = "powershell.*" $Result = Get-PSSessionConfiguration -Name $endpointWildcard @@ -478,7 +467,7 @@ namespace PowershellTestConfigNamespace } AfterEach { - #Unregister-PSSessionConfiguration -Name $TestSessionConfigName -Force -NoServiceRestart -ErrorAction SilentlyContinue + Unregister-PSSessionConfiguration -Name $TestSessionConfigName -Force -NoServiceRestart -ErrorAction SilentlyContinue } It "Validate Register-PSSessionConfiguration -name -path" { @@ -868,7 +857,8 @@ namespace PowershellTestConfigNamespace } } } -finally { +finally +{ $global:PSDefaultParameterValues = $originalDefaultParameterValues } From a43318b179d3f4e6f08032d57f79079ef49ec1af Mon Sep 17 00:00:00 2001 From: Mike Richmond Date: Wed, 26 Jul 2017 14:35:20 -0700 Subject: [PATCH 04/12] Fixing merge error and tests --- .../resources/RemotingErrorIdStrings.resx | 1 + .../PSSessionConfiguration.Tests.ps1 | 28 ++++--------------- 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/src/System.Management.Automation/resources/RemotingErrorIdStrings.resx b/src/System.Management.Automation/resources/RemotingErrorIdStrings.resx index 97e2247985c..30290babfd6 100644 --- a/src/System.Management.Automation/resources/RemotingErrorIdStrings.resx +++ b/src/System.Management.Automation/resources/RemotingErrorIdStrings.resx @@ -1644,6 +1644,7 @@ All WinRM sessions connected to Windows PowerShell session configurations, such The SSH transport process has abruptly terminated causing this remote session to break. + PowerShell Core does not support WOW64. The binary must match the architecture of the processor. diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 index 4d08ec0a572..ff6343a26ba 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 @@ -1,4 +1,3 @@ - try { # Skip all tests on non-windows and non-PowerShellCore and non-elevated platforms. @@ -101,7 +100,7 @@ try # Create new Config File function CreateTestConfigFile { - $TestConfigFileLoc = join-path $env:SystemDrive "MultiMachineTestData\Remoting\cmdlets" + $TestConfigFileLoc = join-path $TestDrive "Remoting" if(-not (Test-path $TestConfigFileLoc)) { $null = New-Item -Path $TestConfigFileLoc -ItemType Directory -Force -ErrorAction Stop @@ -435,7 +434,7 @@ namespace PowershellTestConfigNamespace return $TestAssemblyName } - $global:TestDir = join-path $env:SystemDrive "MultiMachineTestData\Remoting\cmdlets" + $global:TestDir = join-path $TestDrive "Remoting" if(-not (Test-Path $global:TestDir)) { $null = New-Item -path $global:TestDir -ItemType Directory @@ -606,7 +605,7 @@ namespace PowershellTestConfigNamespace It "Validate New-PSSessionConfigurationFile can successfully create a valid PSSessionConfigurationFile" { - $configFilePath = join-path $env:SystemDrive "SamplePSSessionConfigurationFile.pssc" + $configFilePath = join-path $TestDrive "SamplePSSessionConfigurationFile.pssc" try { New-PSSessionConfigurationFile $configFilePath @@ -756,31 +755,16 @@ namespace PowershellTestConfigNamespace It "Validate FullyQualifiedErrorId from Test-PSSessionConfigurationFile when an invalid pssc file is provided as input and -Verbose parameter is specified" { - $configFilePath = join-path $env:SystemDrive "SamplePSSessionConfigurationFile.pssc" + $configFilePath = join-path $TestDrive "SamplePSSessionConfigurationFile.pssc" "InvalidData" | Out-File $configFilePath - try - { - Test-PSSessionConfigurationFile $configFilePath -Verbose -ErrorAction Stop - throw "No Exception!" - } - catch - { - $_.FullyQualifiedErrorId | Should Be "PSSessionConfigurationFileNotFound,Microsoft.PowerShell.Commands.TestPSSessionConfigurationFileCommand" - } - finally - { - if(Test-Path $configFilePath) - { - Remove-Item $configFilePath -Force - } - } + Test-PSSessionConfigurationFile $configFilePath -Verbose -ErrorAction Stop | Should Be $false } It "Test case verifies that the generated config file passes validation" { # Path the config file - $configFilePath = join-path $env:SystemDrive "SamplePSSessionConfigurationFile.pssc" + $configFilePath = join-path $TestDrive "SamplePSSessionConfigurationFile.pssc" $updatedFunctionDefn = @() foreach($currentDefination in $parmMap.FunctionDefinitions) From 9f9f4f81f701e95d1072663b7e0457ff9be64202 Mon Sep 17 00:00:00 2001 From: Mike Richmond Date: Wed, 26 Jul 2017 15:08:40 -0700 Subject: [PATCH 05/12] Add new cmdlets to DefaultCommands test --- test/powershell/engine/DefaultCommands.Tests.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/powershell/engine/DefaultCommands.Tests.ps1 b/test/powershell/engine/DefaultCommands.Tests.ps1 index 42760abf08c..50ddb81b4d6 100644 --- a/test/powershell/engine/DefaultCommands.Tests.ps1 +++ b/test/powershell/engine/DefaultCommands.Tests.ps1 @@ -206,7 +206,7 @@ Describe "Verify approved aliases list" -Tags "CI" { "Cmdlet", "Debug-Runspace", , $($FullCLR -or $CoreWindows -or $CoreUnix) "Cmdlet", "Disable-ComputerRestore", , $($FullCLR ) "Cmdlet", "Disable-PSBreakpoint", , $($FullCLR -or $CoreWindows -or $CoreUnix) -"Cmdlet", "Disable-PSRemoting", , $($FullCLR ) +"Cmdlet", "Disable-PSRemoting", , $($FullCLR -or $CoreWindows ) "Cmdlet", "Disable-PSSessionConfiguration", , $($FullCLR -or $CoreWindows -or $CoreUnix) "Cmdlet", "Disable-RunspaceDebug", , $($FullCLR -or $CoreWindows -or $CoreUnix) "Cmdlet", "Disable-WSManCredSSP", , $($FullCLR -or $CoreWindows ) @@ -214,7 +214,7 @@ Describe "Verify approved aliases list" -Tags "CI" { "Cmdlet", "Disconnect-WSMan", , $($FullCLR -or $CoreWindows ) "Cmdlet", "Enable-ComputerRestore", , $($FullCLR ) "Cmdlet", "Enable-PSBreakpoint", , $($FullCLR -or $CoreWindows -or $CoreUnix) -"Cmdlet", "Enable-PSRemoting", , $($FullCLR ) +"Cmdlet", "Enable-PSRemoting", , $($FullCLR -or $CoreWindows ) "Cmdlet", "Enable-PSSessionConfiguration", , $($FullCLR -or $CoreWindows -or $CoreUnix) "Cmdlet", "Enable-RunspaceDebug", , $($FullCLR -or $CoreWindows -or $CoreUnix) "Cmdlet", "Enable-WSManCredSSP", , $($FullCLR -or $CoreWindows ) From 8467ce473b53ec91011298e15b1bee35c70b5da2 Mon Sep 17 00:00:00 2001 From: Mike Richmond Date: Wed, 26 Jul 2017 16:02:29 -0700 Subject: [PATCH 06/12] Fix DefaultCommands for non-Windows --- .../engine/InitialSessionState.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/System.Management.Automation/engine/InitialSessionState.cs b/src/System.Management.Automation/engine/InitialSessionState.cs index 30cbcf33d33..9f6783793ff 100644 --- a/src/System.Management.Automation/engine/InitialSessionState.cs +++ b/src/System.Management.Automation/engine/InitialSessionState.cs @@ -5962,9 +5962,11 @@ private static void InitializeCoreCmdletsAndProviders( {"Connect-PSSession", new SessionStateCmdletEntry("Connect-PSSession", typeof(ConnectPSSessionCommand), helpFile) }, {"Debug-Job", new SessionStateCmdletEntry("Debug-Job", typeof(DebugJobCommand), helpFile) }, {"Disable-PSSessionConfiguration", new SessionStateCmdletEntry("Disable-PSSessionConfiguration", typeof(DisablePSSessionConfigurationCommand), helpFile) }, - {"Disable-PSRemoting", new SessionStateCmdletEntry("Disable-PSRemoting", typeof(DisablePSRemotingCommand), helpFile) }, {"Disconnect-PSSession", new SessionStateCmdletEntry("Disconnect-PSSession", typeof(DisconnectPSSessionCommand), helpFile) }, +#if !UNIX + {"Disable-PSRemoting", new SessionStateCmdletEntry("Disable-PSRemoting", typeof(DisablePSRemotingCommand), helpFile) }, {"Enable-PSRemoting", new SessionStateCmdletEntry("Enable-PSRemoting", typeof(EnablePSRemotingCommand), helpFile) }, +#endif {"Enable-PSSessionConfiguration", new SessionStateCmdletEntry("Enable-PSSessionConfiguration", typeof(EnablePSSessionConfigurationCommand), helpFile) }, {"Enter-PSHostProcess", new SessionStateCmdletEntry("Enter-PSHostProcess", typeof(EnterPSHostProcessCommand), helpFile) }, {"Enter-PSSession", new SessionStateCmdletEntry("Enter-PSSession", typeof(EnterPSSessionCommand), helpFile) }, From 7189cdc9337038c80ad398d315c64079b3c7ccd1 Mon Sep 17 00:00:00 2001 From: Mike Richmond Date: Thu, 27 Jul 2017 10:58:03 -0700 Subject: [PATCH 07/12] Remove IsPowerShellCore and binary placement in the Publish directory --- build.psm1 | 10 - .../remoting/commands/CustomShellCommands.cs | 195 ++++++------------ 2 files changed, 67 insertions(+), 138 deletions(-) diff --git a/build.psm1 b/build.psm1 index 5a8aa52d95c..1e06405c285 100644 --- a/build.psm1 +++ b/build.psm1 @@ -256,16 +256,6 @@ cmd.exe /C cd /d "$location" "&" "$($vcPath)\vcvarsall.bat" "$Arch" "&" cmake "$ log " Copying $srcPath to $dstPath" Copy-Item $srcPath $dstPath - - if ($_ -match "pwrshplugin.") - { - # Copy the plugin dll to the output directory so that the remoting tests can run out of the default build directory - $tempOptions = New-PSOptions -Configuration ($script:Options).Configuration -Framework ($script:Options).Framework -Runtime ($script:Options).Runtime - $pluginDst = [IO.Path]::GetDirectoryName($tempOptions.Output) # skip the powershell.exe that gets added on the end - New-Item -Type Directory $pluginDst -Force - log " Copying $srcPath to $pluginDst" - Copy-Item $srcPath $pluginDst - } } # Place the remoting configuration script in the same directory diff --git a/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs b/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs index a223e011a2f..7041e96f405 100644 --- a/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs +++ b/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs @@ -488,19 +488,14 @@ protected override void BeginProcessing() } } -#if CORECLR - if (Platform.IsPowerShellCore) + string pluginPath = PSSessionConfigurationCommandUtilities.GetWinrmPluginDllPath(); + pluginPath = Environment.ExpandEnvironmentVariables(pluginPath); + if (!System.IO.File.Exists(pluginPath)) { - string pluginPath = PSSessionConfigurationCommandUtilities.GetWinrmPluginDllPath(); - pluginPath = Environment.ExpandEnvironmentVariables(pluginPath); - if (!System.IO.File.Exists(pluginPath)) - { - PSInvalidOperationException ioe = new PSInvalidOperationException( - StringUtil.Format(RemotingErrorIdStrings.PluginDllMissing, RemotingConstants.PSPluginDLLName)); - ThrowTerminatingError(ioe.ErrorRecord); - } + PSInvalidOperationException ioe = new PSInvalidOperationException( + StringUtil.Format(RemotingErrorIdStrings.PluginDllMissing, RemotingConstants.PSPluginDLLName)); + ThrowTerminatingError(ioe.ErrorRecord); } -#endif } /// @@ -1024,12 +1019,11 @@ private string ConstructPluginContent(out string srcConfigFilePath, out string d // Copy File. string destConfigFileDirectory = System.IO.Path.GetDirectoryName(destConfigFilePath); - if (Platform.IsPowerShellCore) - { - // The directory is not auto-created for PowerShell Core. - // The call will create it or return its path if it already exists - System.IO.Directory.CreateDirectory(destConfigFileDirectory); - } + + // The directory is not auto-created for PowerShell Core. + // The call will create it or return its path if it already exists + System.IO.Directory.CreateDirectory(destConfigFileDirectory); + File.Copy(srcConfigFilePath, destConfigFilePath, true); initParameters.Append(string.Format(CultureInfo.InvariantCulture, @@ -1566,18 +1560,11 @@ internal static string GetRunAsVirtualAccountGroupsString(string[] groups) /// internal static string GetWinrmPluginShellName() { -#if CORECLR - if (Platform.IsPowerShellCore) - { - // PowerShell Core uses a versioned directory to hold the plugin - Hashtable versionTable = PSVersionInfo.GetPSVersionTable(); - // TODO: This should be PSVersionInfo.PSVersionName once we get - // closer to release. Right now it doesn't support alpha versions. - return System.String.Concat("PowerShell.", (string)versionTable["GitCommitId"]); - } - // else it is WindowsPowerShell for CoreCLR and uses the DefaultShellName -#endif - return RemotingConstants.DefaultShellName; + // PowerShell Core uses a versioned directory to hold the plugin + Hashtable versionTable = PSVersionInfo.GetPSVersionTable(); + // TODO: This should be PSVersionInfo.PSVersionName once we get + // closer to release. Right now it doesn't support alpha versions. + return System.String.Concat("PowerShell.", (string)versionTable["GitCommitId"]); } /// @@ -1586,18 +1573,11 @@ internal static string GetWinrmPluginShellName() /// internal static string GetWinrmPluginDllPath() { - string pluginDllDirectory = "%windir%\\system32"; -#if CORECLR - if (Platform.IsPowerShellCore) - { - // PowerShell Core uses its versioned directory instead of system32 - Hashtable versionTable = PSVersionInfo.GetPSVersionTable(); - // TODO: This should be PSVersionInfo.PSVersionName once we get - // closer to release. Right now it doesn't support alpha versions. - pluginDllDirectory = System.IO.Path.Combine("%windir%\\system32\\PowerShell", (string)versionTable["GitCommitId"]); - } -#endif - return System.IO.Path.Combine(pluginDllDirectory, RemotingConstants.PSPluginDLLName); + // PowerShell Core uses its versioned directory instead of system32 + Hashtable versionTable = PSVersionInfo.GetPSVersionTable(); + // TODO: This should be PSVersionInfo.PSVersionName once we get + // closer to release. Right now it doesn't support alpha versions. + pluginDllDirectory = System.IO.Path.Combine("%windir%\\system32\\PowerShell", (string)versionTable["GitCommitId"]); } #endregion @@ -2568,21 +2548,10 @@ function Unregister-PSSessionConfiguration else {{ if (($pluginFileName.Value -match 'system32\\{0}') -OR - ($pluginFileName.Value -match 'syswow64\\{0}')) + ($pluginFileName.Value -match 'syswow64\\{0}')) {{ - # Filter out WindowsPowerShell endpoints when running as PowerShell Core - if ([System.Management.Automation.Platform]::IsPowerShellCore) - {{ - return - }} - }} - else - {{ - # Filter out PowerShell Core endpoints when running as WindowsPowerShell - if (![System.Management.Automation.Platform]::IsPowerShellCore) - {{ - return - }} + # Filter out WindowsPowerShell endpoints when running as PowerShell Core + return }} }} @@ -2884,29 +2853,18 @@ function ExtractPluginProperties([string]$pluginDir, $objectToWriteTo) $customPluginObject = new-object object $customPluginObject.pstypenames.Insert(0, '{0}') ExtractPluginProperties ""$($_.PSPath)"" $customPluginObject - # this is powershell based custom shell only if its plugin dll is pwrshplugin.dll + # This is powershell based custom shell only if its plugin dll is pwrshplugin.dll if (($customPluginObject.FileName) -and ($customPluginObject.FileName -match '{1}')) {{ - # Filter the endpoints based on the typeof PowerShell that is - # executing the cmdlet. - if (($customPluginObject.FileName -match 'system32\\{1}') -OR # WindowsPowerShell - ($customPluginObject.FileName -match 'syswow64\\{1}')) # WOW64 WindowsPowerShell - {{ - # Add WindowsPowerShell endpoints when running as WindowsPowerShell - if (![System.Management.Automation.Platform]::IsPowerShellCore) - {{ - $shellsFound++ - $customPluginObject - }} - }} - else # {1} in another location indicates that it is a PowerShell Core endpoint + # Filter the endpoints based on the typeof PowerShell that is + # executing the cmdlet. {1} in another location indicates that it + # is a PowerShell Core endpoint + if (!($customPluginObject.FileName -match 'system32\\{1}') -AND # WindowsPowerShell + !($customPluginObject.FileName -match 'syswow64\\{1}')) # WOW64 WindowsPowerShell {{ - # Add the PowerShell Core endpoint when running as PowerShell Core - if ([System.Management.Automation.Platform]::IsPowerShellCore) - {{ - $shellsFound++ - $customPluginObject - }} + # Add the PowerShell Core endpoint when running as PowerShell Core + $shellsFound++ + $customPluginObject }} }} }} # end of foreach @@ -3163,24 +3121,12 @@ function Set-RunAsCredential{{ }} else {{ + # Filter out WindowsPowerShell endpoints when running as PowerShell Core if (($pluginFileName.Value -match 'system32\\{0}') -OR ($pluginFileName.Value -match 'syswow64\\{0}')) {{ - # Filter out WindowsPowerShell endpoints when running as PowerShell Core - if ([System.Management.Automation.Platform]::IsPowerShellCore) - {{ - Write-Error $pluginForWindowsPowerShellMsg - return - }} - }} - else - {{ - # Filter out PowerShell Core endpoints when running as WindowsPowerShell - if (![System.Management.Automation.Platform]::IsPowerShellCore) - {{ - Write-Error $pluginForPowerShellCoreMsg - return - }} + Write-Error $pluginForWindowsPowerShellMsg + return }} }} @@ -4922,49 +4868,42 @@ function Enable-PSRemoting if ((!$endpoint) -and ($force -or $pscmdlet.ShouldProcess($qMessage, $captionForRegisterDefault))) {{ - # Create the default endpoint for the appropriate environment - if ([System.Management.Automation.Platform]::IsPowerShellCore) + $resolvedPluginInstallPath = """" + # + # Section 1: + # Move pwrshplugin.dll from $PSHOME to the endpoint directory + # + $pluginInstallPath = Join-Path ""$env:WINDIR\System32\PowerShell"" $psversiontable.GitCommitId + if (!(Test-Path $pluginInstallPath)) {{ - $resolvedPluginInstallPath = """" - # - # Section 1: - # Move pwrshplugin.dll from $PSHOME to the endpoint directory - # - $pluginInstallPath = Join-Path ""$env:WINDIR\System32\PowerShell"" $psversiontable.GitCommitId - if (!(Test-Path $pluginInstallPath)) - {{ - $resolvedPluginInstallPath = New-Item -Type Directory -Path $pluginInstallPath - }} - else - {{ - $resolvedPluginInstallPath = Resolve-Path $pluginInstallPath - }} - if (!(Test-Path $resolvedPluginInstallPath\{5})) - {{ - Copy-Item $PSHOME\{5} $resolvedPluginInstallPath -Force - if (!(Test-Path $resolvedPluginInstallPath\{5})) - {{ - Write-Error ($errorMsgUnableToInstallPlugin -f ""{5}"", $resolvedPluginInstallPath) - return - }} - }} - - # - # Section 2: - # Generate the Plugin Configuration File - # - Generate-PluginConfigFile $resolvedPluginInstallPath - - # - # Section 3: - # Register the endpoint - # - $null = Register-PSSessionConfiguration -Name {0} -force + $resolvedPluginInstallPath = New-Item -Type Directory -Path $pluginInstallPath }} else {{ - $null = Register-PSSessionConfiguration {0} -force + $resolvedPluginInstallPath = Resolve-Path $pluginInstallPath }} + if (!(Test-Path $resolvedPluginInstallPath\{5})) + {{ + Copy-Item $PSHOME\{5} $resolvedPluginInstallPath -Force + if (!(Test-Path $resolvedPluginInstallPath\{5})) + {{ + Write-Error ($errorMsgUnableToInstallPlugin -f ""{5}"", $resolvedPluginInstallPath) + return + }} + }} + + # + # Section 2: + # Generate the Plugin Configuration File + # + Generate-PluginConfigFile $resolvedPluginInstallPath + + # + # Section 3: + # Register the endpoint + # + $null = Register-PSSessionConfiguration -Name {0} -force + set-item -WarningAction SilentlyContinue wsman:\localhost\plugin\{0}\Quotas\MaxShellsPerUser -value ""25"" -confirm:$false set-item -WarningAction SilentlyContinue wsman:\localhost\plugin\{0}\Quotas\MaxIdleTimeoutms -value {4} -confirm:$false restart-service winrm -confirm:$false From ce0ab1ce26707e49cf44f88bb3a34ed34a45b027 Mon Sep 17 00:00:00 2001 From: Mike Richmond Date: Thu, 27 Jul 2017 11:59:54 -0700 Subject: [PATCH 08/12] Fix plugin dll path --- .../engine/remoting/commands/CustomShellCommands.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs b/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs index 7041e96f405..f137af05771 100644 --- a/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs +++ b/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs @@ -1577,7 +1577,8 @@ internal static string GetWinrmPluginDllPath() Hashtable versionTable = PSVersionInfo.GetPSVersionTable(); // TODO: This should be PSVersionInfo.PSVersionName once we get // closer to release. Right now it doesn't support alpha versions. - pluginDllDirectory = System.IO.Path.Combine("%windir%\\system32\\PowerShell", (string)versionTable["GitCommitId"]); + string pluginDllDirectory = System.IO.Path.Combine("%windir%\\system32\\PowerShell", (string)versionTable["GitCommitId"]); + return System.IO.Path.Combine(pluginDllDirectory, RemotingConstants.PSPluginDLLName); } #endregion From 360b3cd61b4fb04de121a9707a2b16a25925da10 Mon Sep 17 00:00:00 2001 From: Mike Richmond Date: Thu, 27 Jul 2017 12:21:01 -0700 Subject: [PATCH 09/12] Remove trailing whitespace from new lines --- .../engine/remoting/commands/CustomShellCommands.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs b/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs index f137af05771..c28b7939ddf 100644 --- a/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs +++ b/src/System.Management.Automation/engine/remoting/commands/CustomShellCommands.cs @@ -125,7 +125,7 @@ function Register-PSSessionConfiguration new-item -path WSMan:\localhost\Plugin -file ""$filepath"" -name ""$pluginName"" }} - if ($? -and $runAsUserName) + if ($? -and $runAsUserName) {{ try {{ $runAsCredential = new-object system.management.automation.PSCredential($runAsUserName, $runAsPassword) @@ -3124,7 +3124,7 @@ function Set-RunAsCredential{{ {{ # Filter out WindowsPowerShell endpoints when running as PowerShell Core if (($pluginFileName.Value -match 'system32\\{0}') -OR - ($pluginFileName.Value -match 'syswow64\\{0}')) + ($pluginFileName.Value -match 'syswow64\\{0}')) {{ Write-Error $pluginForWindowsPowerShellMsg return @@ -4847,7 +4847,7 @@ function Enable-PSRemoting # # This cmdlet will make sure default powershell end points exist upon successful completion. - # + # # Windows PowerShell: # Microsoft.PowerShell # Microsoft.PowerShell32 (wow64) @@ -4902,7 +4902,7 @@ function Enable-PSRemoting # # Section 3: # Register the endpoint - # + # $null = Register-PSSessionConfiguration -Name {0} -force set-item -WarningAction SilentlyContinue wsman:\localhost\plugin\{0}\Quotas\MaxShellsPerUser -value ""25"" -confirm:$false @@ -4957,7 +4957,7 @@ function Enable-PSRemoting }} $qMessage = $queryForRegisterDefault -f ""{0}32"",""Register-PSSessionConfiguration {0}32 -processorarchitecture x86 -force"" - if ((!$endpoint) -and + if ((!$endpoint) -and ($force -or $pscmdlet.ShouldProcess($qMessage, $captionForRegisterDefault))) {{ $null = Register-PSSessionConfiguration {0}32 -processorarchitecture x86 -force From 7115752f1c9814e04aa6887ed62a2f51f4583d04 Mon Sep 17 00:00:00 2001 From: Mike Richmond Date: Mon, 31 Jul 2017 21:37:01 -0700 Subject: [PATCH 10/12] Code review fixes --- .../PSSessionConfiguration.Tests.ps1 | 50 +++++++++++-------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 index ff6343a26ba..10efadae2fa 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 @@ -364,10 +364,10 @@ try # Create Test Startup Script function CreateStartupScript { $ScriptContent = @" -`$global:testvariable = "testValue" +`$script:testvariable = "testValue" "@ - $TestScript = join-path $global:TestDir "StartupTestScript.ps1" + $TestScript = join-path $script:TestDir "StartupTestScript.ps1" $null = Set-Content -path $TestScript -Value $ScriptContent return $TestScript @@ -376,7 +376,7 @@ try # Create new Config File function CreateTestConfigFile { - $TestConfigFile = join-path $global:TestDir "TestConfigFile.pssc" + $TestConfigFile = join-path $script:TestDir "TestConfigFile.pssc" $null = New-PSSessionConfigurationFile -Path $TestConfigFile -SessionType Default return $TestConfigFile } @@ -388,7 +388,7 @@ return `$true } Export-ModuleMember IsTestModuleImported "@ - $TestModuleFileLoc = $global:TestDir + $TestModuleFileLoc = $script:TestDir if(-not (Test-path $TestModuleFileLoc)) { @@ -425,26 +425,32 @@ namespace PowershellTestConfigNamespace } } "@ - $global:Sma = [reflection.assembly]::load('System.Management.Automation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL').location - $global:SourceFile = join-path $global:TestDir "PowershellTestConfig.cs" - $PscConfigDef | out-file $global:SourceFile -Encoding ascii -Force + $script:Sma = [reflection.assembly]::load('System.Management.Automation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL').location + $script:SourceFile = join-path $script:TestAssemblyDir "PowershellTestConfig.cs" + $PscConfigDef | out-file $script:SourceFile -Encoding ascii -Force $TestAssemblyName = "TestAssembly.dll" - $TestAssemblyPath = join-path $global:TestDir $TestAssemblyName - Add-Type -path $global:SourceFile -ReferencedAssemblies $global:Sma -OutputAssembly $TestAssemblyPath + $TestAssemblyPath = join-path $script:TestAssemblyDir $TestAssemblyName + Add-Type -path $script:SourceFile -OutputAssembly $TestAssemblyPath return $TestAssemblyName } - $global:TestDir = join-path $TestDrive "Remoting" - if(-not (Test-Path $global:TestDir)) + $script:TestDir = join-path $TestDrive "Remoting" + if(-not (Test-Path $script:TestDir)) { - $null = New-Item -path $global:TestDir -ItemType Directory + $null = New-Item -path $script:TestDir -ItemType Directory + } + + $script:TestAssemblyDir = [System.IO.Path]::GetTempPath() + if(-not (Test-Path $script:TestAssemblyDir)) + { + $null = New-Item -path $script:TestAssemblyDir -ItemType Directory } $LocalConfigFilePath = CreateTestConfigFile $LocalStartupScriptPath = CreateStartupScript $LocalTestModulePath = CreateTestModule $LocalTestAssemblyName = CreateTestAssembly - $LocalTestDir = $global:TestDir + $LocalTestDir = $script:TestDir } } @@ -494,7 +500,7 @@ namespace PowershellTestConfigNamespace $null = Register-PSSessionConfiguration -Name $TestSessionConfigName -path $LocalConfigFilePath -StartupScript $LocalStartupScriptPath -Force - ValidateRemoteEndpoint -TestSessionConfigName $TestSessionConfigName -ScriptToExecute "return `$global:testvariable" -ExpectedOutput "testValue" -ExpectedError $null + ValidateRemoteEndpoint -TestSessionConfigName $TestSessionConfigName -ScriptToExecute "return `$script:testvariable" -ExpectedOutput "testValue" -ExpectedError $null } @@ -513,10 +519,10 @@ namespace PowershellTestConfigNamespace ValidateRemoteEndpoint -TestSessionConfigName $TestSessionConfigName -ScriptToExecute "return IsTestModuleImported" -ExpectedOutput $true -ExpectedError $null } - It "Validate Register-PSSessionConfiguration with ApplicationBase , AssemblyName and ConfigurationTypeName parameter" { + It "Validate Register-PSSessionConfiguration with ApplicationBase, AssemblyName and ConfigurationTypeName parameter" { $TestAssemblyPath = join-path $LocalTestDir $LocalTestAssemblyName - add-type -path $global:SourceFile -ReferencedAssemblies $global:Sma -OutputAssembly $TestAssemblyPath + add-type -path $script:SourceFile -OutputAssembly $TestAssemblyPath $null = Register-PSSessionConfiguration -Name $TestSessionConfigName -ApplicationBase $LocalTestDir -AssemblyName $LocalTestAssemblyName -ConfigurationTypeName "PowershellTestConfigNamespace.PowershellTestConfig" -force ValidateRemoteEndpoint -TestSessionConfigName $TestSessionConfigName -ScriptToExecute $null -ExpectedOutput $true -ExpectedError $null @@ -565,7 +571,7 @@ namespace PowershellTestConfigNamespace $null = Set-PSSessionConfiguration -Name $TestSessionConfigName -StartupScript $LocalStartupScriptPath - ValidateRemoteEndpoint -TestSessionConfigName $TestSessionConfigName -ScriptToExecute "return `$global:testvariable" -ExpectedOutput "testValue" -ExpectedError $null + ValidateRemoteEndpoint -TestSessionConfigName $TestSessionConfigName -ScriptToExecute "return `$script:testvariable" -ExpectedOutput "testValue" -ExpectedError $null } It "Validate Set-PSSessionConfiguration -AccessMode parameter" { @@ -582,13 +588,13 @@ namespace PowershellTestConfigNamespace ValidateRemoteEndpoint -TestSessionConfigName $TestSessionConfigName -ScriptToExecute "return IsTestModuleImported" -ExpectedOutput $true -ExpectedError $null } - It "Validate Set-PSSessionConfiguration with ApplicationBase , AssemblyName and ConfigurationTypeName parameter" { + It "Validate Set-PSSessionConfiguration with ApplicationBase, AssemblyName and ConfigurationTypeName parameter" { $TestAssemblyPath = join-path $LocalTestDir $LocalTestAssemblyName - Add-type -path $global:SourceFile -ReferencedAssemblies $global:Sma -OutputAssembly $TestAssemblyPath - $null = Register-PSSessionConfiguration -Name $TestSessionConfigName -ApplicationBase $LocalTestDir -AssemblyName $LocalTestAssemblyName -ConfigurationTypeName "PowershellTestConfigNamespace.PowershellTestConfig" -force + Add-type -path $script:SourceFile -OutputAssembly $TestAssemblyPath + $null = Set-PSSessionConfiguration -Name $TestSessionConfigName -ApplicationBase $LocalTestDir -AssemblyName $LocalTestAssemblyName -ConfigurationTypeName "PowershellTestConfigNamespace.PowershellTestConfig" -force - ValidateRemoteEndpoint -TestSessionConfigName $TestSessionConfigName -ScriptToExecute $null -ExpectedOutput $true -ExpectedError $null + ValidateRemoteEndpoint -TestSessionConfigName $TestSessionConfigName -ScriptToExecute $null -ExpectedOutput $true -ExpectedError $null } } } @@ -843,6 +849,6 @@ namespace PowershellTestConfigNamespace } finally { - $global:PSDefaultParameterValues = $originalDefaultParameterValues + $script:PSDefaultParameterValues = $originalDefaultParameterValues } From ba4cde19afcc9f59d8f0ea806b9b36a22c1dafb8 Mon Sep 17 00:00:00 2001 From: Mike Richmond Date: Tue, 1 Aug 2017 10:04:24 -0700 Subject: [PATCH 11/12] Use existing test assembly instead of creating new ones --- .../PSSessionConfiguration.Tests.ps1 | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 index 10efadae2fa..24121cc0372 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 @@ -521,9 +521,7 @@ namespace PowershellTestConfigNamespace It "Validate Register-PSSessionConfiguration with ApplicationBase, AssemblyName and ConfigurationTypeName parameter" { - $TestAssemblyPath = join-path $LocalTestDir $LocalTestAssemblyName - add-type -path $script:SourceFile -OutputAssembly $TestAssemblyPath - $null = Register-PSSessionConfiguration -Name $TestSessionConfigName -ApplicationBase $LocalTestDir -AssemblyName $LocalTestAssemblyName -ConfigurationTypeName "PowershellTestConfigNamespace.PowershellTestConfig" -force + $null = Register-PSSessionConfiguration -Name $TestSessionConfigName -ApplicationBase $script:TestAssemblyDir -AssemblyName $LocalTestAssemblyName -ConfigurationTypeName "PowershellTestConfigNamespace.PowershellTestConfig" -force ValidateRemoteEndpoint -TestSessionConfigName $TestSessionConfigName -ScriptToExecute $null -ExpectedOutput $true -ExpectedError $null } @@ -590,9 +588,7 @@ namespace PowershellTestConfigNamespace It "Validate Set-PSSessionConfiguration with ApplicationBase, AssemblyName and ConfigurationTypeName parameter" { - $TestAssemblyPath = join-path $LocalTestDir $LocalTestAssemblyName - Add-type -path $script:SourceFile -OutputAssembly $TestAssemblyPath - $null = Set-PSSessionConfiguration -Name $TestSessionConfigName -ApplicationBase $LocalTestDir -AssemblyName $LocalTestAssemblyName -ConfigurationTypeName "PowershellTestConfigNamespace.PowershellTestConfig" -force + $null = Set-PSSessionConfiguration -Name $TestSessionConfigName -ApplicationBase $script:TestAssemblyDir -AssemblyName $LocalTestAssemblyName -ConfigurationTypeName "PowershellTestConfigNamespace.PowershellTestConfig" -force ValidateRemoteEndpoint -TestSessionConfigName $TestSessionConfigName -ScriptToExecute $null -ExpectedOutput $true -ExpectedError $null } From 1db21fdb60bdfaf9af420eadf6b96ee239a98cab Mon Sep 17 00:00:00 2001 From: Mike Richmond Date: Tue, 1 Aug 2017 13:42:34 -0700 Subject: [PATCH 12/12] Code review fixes --- .../Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 index 24121cc0372..8df5594ab7d 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 @@ -425,7 +425,6 @@ namespace PowershellTestConfigNamespace } } "@ - $script:Sma = [reflection.assembly]::load('System.Management.Automation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL').location $script:SourceFile = join-path $script:TestAssemblyDir "PowershellTestConfig.cs" $PscConfigDef | out-file $script:SourceFile -Encoding ascii -Force $TestAssemblyName = "TestAssembly.dll" @@ -845,6 +844,6 @@ namespace PowershellTestConfigNamespace } finally { - $script:PSDefaultParameterValues = $originalDefaultParameterValues + $global:PSDefaultParameterValues = $originalDefaultParameterValues }