Add Remoting and Job tests (#4928)

This commit is contained in:
Aditya Patwardhan 2017-10-02 13:43:43 -07:00 committed by Travis Plunk
parent d73e97464c
commit 1e271ea187
6 changed files with 600 additions and 64 deletions

View file

@ -785,13 +785,6 @@ namespace Microsoft.PowerShell.Commands
throw new InvalidOperationException(RemotingErrorIdStrings.AsJobAndDisconnectedError);
}
if (this.InvokeAndDisconnect &&
(this.ComputerName == null || this.ComputerName.Length == 0) &&
(this.ConnectionUri == null || this.ConnectionUri.Length == 0))
{
throw new InvalidOperationException(RemotingErrorIdStrings.InvokeDisconnectedWithoutComputerName);
}
if (MyInvocation.BoundParameters.ContainsKey("SessionName") && !this.InvokeAndDisconnect)
{
throw new InvalidOperationException(RemotingErrorIdStrings.SessionNameWithoutInvokeDisconnected);

View file

@ -911,9 +911,6 @@ Do you want to continue?</value>
<data name="JobIdentifierNull" xml:space="preserve">
<value>The JobIdentifier provided must not be null. Please provide a valid JobIdentifier.</value>
</data>
<data name="InvokeDisconnectedWithoutComputerName" xml:space="preserve">
<value>No computer names or connection Uris were specified. You must provide a computer name or connection Uri when invoking a command with the -Disconnected switch.</value>
</data>
<data name="JobBlockedSoWaitJobCannotContinue" xml:space="preserve">
<value>The Wait-Job cmdlet cannot finish working, because one or more jobs are blocked waiting for user interaction. Process interactive job output by using the Receive-Job cmdlet, and then try again.</value>
</data>

View file

@ -1,38 +1,285 @@
Describe 'Basic Job Tests' -Tags 'CI' {
BeforeAll {
$job = Start-Job {1}
}
# Make sure we do not have any jobs running
Get-Job | Remove-Job -Force
$timeBeforeStartedJob = Get-Date
$startedJob = Start-Job -Name 'StartedJob' -ScriptBlock { 1 + 1 } | Wait-Job
$timeAfterStartedJob = Get-Date
It 'Test job creation' {
$job | should not be $null
}
function script:ValidateJobInfo($job, $state, $hasMoreData, $command)
{
$job.State | Should BeExactly $state
$job.HasMoreData | Should Be $hasMoreData
It 'Test job State' {
Wait-Job $job -Timeout 60
$job.JobStateInfo.State -eq 'Completed' | should be $true
}
It 'Job output test' {
Receive-Job $job -wait | should be 1
}
It "Create job with native command" {
try {
$nativeJob = Start-job { powershell -c 1+1 }
$nativeJob | Wait-Job
$nativeJob.State | Should BeExactly "Completed"
$nativeJob.HasMoreData | Should Be $true
Receive-Job $nativeJob | Should BeExactly 2
Remove-Job $nativeJob
{ Get-Job $nativeJob -ErrorAction Stop } | ShouldBeErrorId "JobWithSpecifiedNameNotFound,Microsoft.PowerShell.Commands.GetJobCommand"
}
finally {
Remove-Job $nativeJob -Force -ErrorAction SilentlyContinue
if($command -ne $null)
{
$job.Command | Should BeExactly $command
}
}
}
AfterAll {
Remove-Job $job -Force
$startedJob | Remove-Job -Force -ErrorAction SilentlyContinue
}
}
Context 'Basic tests' {
AfterEach {
Get-Job | Where-Object { $_.Id -ne $startedJob.Id } | Remove-Job -ErrorAction SilentlyContinue -Force
}
It 'Can start, wait and receive a Job' {
$job = Start-Job -ScriptBlock { 1 + 1 }
$result = $job | Wait-Job | Receive-Job
ValidateJobInfo -job $job -state 'Completed' -hasMoreData $false -command ' 1 + 1 '
$result | Should Be 2
}
It 'Can run nested jobs' {
$job = Start-Job -ScriptBlock { Start-Job -ScriptBlock { 1 + 1 } | Wait-Job | Receive-Job }
ValidateJobInfo -job $job -state 'Running' -hasMoreData $true -command ' Start-Job -ScriptBlock { 1 + 1 } | Wait-Job | Receive-Job '
$result = $job | Wait-Job | Receive-Job
$result | Should Be 2
}
It 'Can get errors messages from job' {
$job = Start-Job -ScriptBlock { throw 'MyError' } | Wait-Job
Receive-Job -Job $job -ErrorVariable ev -ErrorAction SilentlyContinue
$ev[0].Exception.Message | Should BeExactly 'MyError'
}
It 'Can get warning messages from job' {
$job = Start-Job -ScriptBlock { Write-Warning 'MyWarning' } | Wait-Job
Receive-Job -Job $job -WarningVariable wv -WarningAction SilentlyContinue
$wv | Should BeExactly 'MyWarning'
}
It 'Can get verbose message from job' {
$job = Start-Job -ScriptBlock { Write-Verbose -Verbose 'MyVerbose' } | Wait-Job
$VerboseMsg = $job.ChildJobs[0].verbose.readall()
$VerboseMsg | Should BeExactly 'MyVerbose'
}
It 'Can get progress message from job' {
$job = Start-Job -ScriptBlock { Write-Progress -Activity 1 -Status 2 } | Wait-Job
$ProgressMsg = $job.ChildJobs[0].progress.readall()
$ProgressMsg[0].Activity | Should BeExactly 1
$ProgressMsg[0].StatusDescription | Should BeExactly 2
}
It "Create job with native command" {
try {
$nativeJob = Start-job { powershell -c 1+1 }
$nativeJob | Wait-Job
$nativeJob.State | Should BeExactly "Completed"
$nativeJob.HasMoreData | Should Be $true
Receive-Job $nativeJob | Should BeExactly 2
Remove-Job $nativeJob
{ Get-Job $nativeJob -ErrorAction Stop } | ShouldBeErrorId "JobWithSpecifiedNameNotFound,Microsoft.PowerShell.Commands.GetJobCommand"
}
finally {
Remove-Job $nativeJob -Force -ErrorAction SilentlyContinue
}
}
}
Context 'Wait-Job tests' {
BeforeAll {
$waitJobTestCases = @(
@{ parameters = @{ Name = $startedJob.Name } ; property = '-Name'},
@{ parameters = @{ Id = $startedJob.Id } ; property = '-Id'},
@{ parameters = @{ Job = $startedJob } ; property = '-Job'},
@{ parameters = @{ InstanceId = $startedJob.InstanceId } ; property = '-InstanceId'},
@{ parameters = @{ State = $startedJob.State } ; property = '-State'}
)
}
AfterEach {
Get-Job | Where-Object { $_.Id -ne $startedJob.Id } | Remove-Job -ErrorAction SilentlyContinue -Force
}
It 'Can wait for jobs to complete using <property>' -TestCases $waitJobTestCases {
param($parameters)
$job = Wait-Job @parameters
ValidateJobInfo -job $job -state 'Completed' -hasMoreData $true -command ' 1 + 1 '
}
It 'Can wait for any job to complete' {
$jobs = 1..3 | ForEach-Object { $seconds = $_ ; Start-Job -ScriptBlock { Start-Sleep -Seconds $using:seconds ; $using:seconds} }
$waitedJob = Wait-Job -Job $jobs -Any
ValidateJobInfo -job $waitedJob -state 'Completed' -hasMoreData $true -command ' Start-Sleep -Seconds $using:seconds ; $using:seconds'
$result = $waitedJob | Receive-Job
## We check for $result to be less than 4 so that any of the jobs completing first will considered a success.
$result | Should BeLessThan 4
## Check none of the jobs threw errors.
$jobs.Error | Should BeNullOrEmpty
}
It 'Can timeout waiting for a job' {
$job = Start-Job -ScriptBlock { Start-Sleep -Seconds 10 }
$job | Wait-Job -TimeoutSec 1
ValidateJobInfo -job $job -state 'Running' -hasMoreData $true -command ' Start-Sleep -Seconds 10 '
}
}
Context 'Receive-job tests' {
It 'Can Receive-Job with state change events' {
$result = Start-Job -Name 'ReceiveWriteEventsJob' -ScriptBlock { 1 + 1 } | Receive-Job -Wait -WriteEvents
$result.Count | Should Be 3
$result[0] | Should Be 2
$result[1].GetType().FullName | Should BeExactly 'System.Management.Automation.JobStateEventArgs'
}
It 'Can Receive-Job with job object and result' {
$result = Start-Job -ScriptBlock { 1 + 1 } | Receive-Job -Wait -WriteJobInResults
$result.Count | Should Be 2
ValidateJobInfo -job $result[0] -command ' 1 + 1 ' -state 'Completed' -hasMoreData $false
$result[1] | Should Be 2
$result[0] | Remove-Job -Force -ErrorAction SilentlyContinue
}
It 'Can Receive-Job and autoremove' {
$result = Start-Job -Name 'ReceiveJobAutoRemove' -ScriptBlock { 1 + 1 } | Receive-Job -Wait -AutoRemoveJob
$result | Should Be 2
{ Get-Job -Name 'ReceiveJobAutoRemove' -ErrorAction Stop } | ShouldBeErrorId 'JobWithSpecifiedNameNotFound,Microsoft.PowerShell.Commands.GetJobCommand'
}
It 'Can Receive-Job and keep results' {
$job = Start-Job -ScriptBlock { 1 + 1 } | Wait-Job
$result = Receive-Job -Keep -Job $job
$result | Should Be 2
$result2 = Receive-Job -Job $job
$result2 | Should Be 2
$result3 = Receive-Job -Job $job
$result3 | Should BeNullOrEmpty
$job | Remove-Job -Force -ErrorAction SilentlyContinue
}
It 'Can Receive-Job with NoRecurse' {
$job = Start-Job -ScriptBlock { 1 + 1 }
$result = Receive-Job -Wait -NoRecurse -Job $job
$result | Should BeNullOrEmpty
$job | Remove-Job -Force -ErrorAction SilentlyContinue
}
It 'Can Receive-Job using ComputerName' {
$jobName = 'ReceiveUsingComputerName'
$job = Start-Job -ScriptBlock { 1 + 1 } -Name $jobName | Wait-Job
$result = Receive-Job -ComputerName localhost -Job $job
$result | Should Be 2
$job | Remove-Job -Force -ErrorAction SilentlyContinue
}
It 'Can Receive-Job using Location' {
$jobName = 'ReceiveUsingLocation'
$job = Start-Job -ScriptBlock { 1 + 1 } -Name $jobName | Wait-Job
$result = Receive-Job -Location localhost -Job $job
$result | Should Be 2
$job | Remove-Job -Force -ErrorAction SilentlyContinue
}
It 'Can receive a job with -wait switch' {
$job = Start-Job -ScriptBlock { 1 + 1 }
$result = $job | Receive-Job -Wait
ValidateJobInfo -job $job -state 'Completed' -hasMoreData $false -command ' 1 + 1 '
$result | Should Be 2
}
}
Context 'Get-Job tests' {
BeforeAll {
$getJobTestCases = @(
@{ parameters = @{ Name = $startedJob.Name } ; property = 'Name'},
@{ parameters = @{ Id = $startedJob.Id } ; property = 'Id'},
@{ parameters = @{ InstanceId = $startedJob.InstanceId } ; property = 'InstanceId'},
@{ parameters = @{ State = $startedJob.State } ; property = 'State'}
)
$getJobSwitches = @(
@{ parameters = @{ Before = $timeAfterStartedJob }; property = '-Before'},
@{ parameters = @{ After = $timeBeforeStartedJob }; property = '-After'},
@{ parameters = @{ HasMoreData = $true }; property = '-HasMoreData'}
)
$getJobChildJobs = @(
@{ parameters = @{ IncludeChildJob = $true }; property = '-IncludeChildJob'},
@{ parameters = @{ ChildJobState = 'Completed' }; property = '-ChildJobState'}
)
}
AfterEach {
Get-Job | Where-Object { $_.Id -ne $startedJob.Id } | Remove-Job -ErrorAction SilentlyContinue -Force
}
It 'Can Get-Job with <property>' -TestCases $getJobTestCases {
param($parameters)
$job = Get-Job @parameters
ValidateJobInfo -job $job -state 'Completed' -hasMoreData $true -command ' 1 + 1 '
}
It 'Can Get-Job with <property>' -TestCases $getJobSwitches {
param($parameters)
$job = Get-Job @parameters
ValidateJobInfo -job $job -state 'Completed' -hasMoreData $true -Name 'StartedJob'
}
It 'Can Get-Job with <property>' -TestCases $getJobChildJobs {
param($parameters)
$jobs = Get-Job @parameters
$jobs.Count | Should Be 2
ValidateJobInfo -job $jobs[0] -state 'Completed' -hasMoreData $true -Name 'StartedJob'
ValidateJobInfo -job $jobs[1] -state 'Completed' -hasMoreData $true
}
}
Context 'Remove-Job tests' {
# The test pattern used here is different from other tests since there is a scoping issue in Pester.
# If BeforeEach is used then $removeJobTestCases does not bind when the It is called.
# This implementation works around the problem by using a BeforeAll and creating a job inside the It.
BeforeAll {
$removeJobTestCases = @(
@{ property = 'Name'}
@{ property = 'Id'}
@{ property = 'InstanceId'}
@{ property = 'State'}
)
}
It 'Can Remove-Job with <property>' -TestCases $removeJobTestCases {
param($property)
$jobToRemove = Start-Job -ScriptBlock { 1 + 1 } -Name 'JobToRemove' | Wait-Job
$splat = @{ $property = $jobToRemove.$property }
Remove-Job @splat
Get-Job $jobToRemove -ErrorAction SilentlyContinue | Should BeNullOrEmpty
}
}
Context 'Stop-Job tests' {
# The test pattern used here is different from other tests since there is a scoping issue in Pester.
# If BeforeEach is used then $stopJobTestCases does not bind when the It is called.
# This implementation works around the problem by using a BeforeAll and creating a job inside the It.
BeforeAll {
$stopJobTestCases = @(
@{ property = 'Name'}
@{ property = 'Id'}
@{ property = 'InstanceId'}
@{ property = 'State'}
)
# '-Seconds 100' is chosen to be substantially large, so that the job is in running state when Stop-Job is called.
$jobToStop = Start-Job -ScriptBlock { Start-Sleep -Seconds 100 } -Name 'JobToStop'
}
It 'Can Stop-Job with <property>' -TestCases $stopJobTestCases {
param($property)
$splat = @{ $property = $jobToStop.$property }
Stop-Job @splat
ValidateJobInfo -job $jobToStop -state 'Stopped' -hasMoreData $false
}
AfterAll {
Remove-Job $jobToStop -Force -ErrorAction SilentlyContinue
}
}
}

View file

@ -1,4 +1,3 @@
Describe "New-PSSession basic test" -Tag @("CI") {
It "New-PSSession should not crash powershell" {
try {
@ -10,41 +9,78 @@ Describe "New-PSSession basic test" -Tag @("CI") {
}
}
Describe "JEA session Transcprit script test" -Tag @("Feature", 'RequireAdminOnWindows') {
It "Configuration name should be in the transcript header" -Pending {
Describe "JEA session Transcript script test" -Tag @("Feature", 'RequireAdminOnWindows') {
BeforeAll {
$originalDefaultParameterValues = $PSDefaultParameterValues.Clone()
if ( ! $IsWindows )
{
$PSDefaultParameterValues["it:skip"] = $true
}
else
{
Enable-PSRemoting -SkipNetworkProfileCheck
}
}
AfterAll {
$global:PSDefaultParameterValues = $originalDefaultParameterValues
}
It "Configuration name should be in the transcript header" {
[string] $RoleCapDirectory = (New-Item -Path "$TestDrive\RoleCapability" -ItemType Directory -Force).FullName
[string] $PSSessionConfigFile = "$RoleCapDirectory\TestConfig.pssc"
[string] $transScriptFile = "$RoleCapDirectory\*.txt"
try
{
New-PSSessionConfigurationFile -Path $PSSessionConfigFile -TranscriptDirectory $RoleCapDirectory -SessionType RestrictedRemoteServer
Register-PSSessionConfiguration -Name JEA -Path $PSSessionConfigFile -Force -ErrorAction SilentlyContinue
$scriptBlock = {Enter-PSSession -ComputerName Localhost -ConfigurationName JEA; Exit-PSSession}
& $scriptBlock
Register-PSSessionConfiguration -Name JEA -Path $PSSessionConfigFile -Force -ErrorAction SilentlyContinue
$scriptBlock = {Enter-RemoteSession -ComputerName Localhost -ConfigurationName JEA; Exit-PSSession}
# Invoke the script block in a different PowerShell instance so that when TestDrive tries to delete $RoleCapDirectory,
# the transcription has finished and the files are not locked.
[powershell]::Create().AddScript($scriptBlock).Invoke()
$headerFile = Get-ChildItem $transScriptFile | Sort-Object LastWriteTime | Select-Object -Last 1
$header = Get-Content $headerFile | Out-String
$header | Should BeLike "Configuration Name: JEA"
$header | Should Match "Configuration Name: JEA"
}
finally
{
Unregister-PSSessionConfiguration -Name JEA -Force -ErrorAction SilentlyContinue
}
}
}
Describe "JEA session Get-Help test" -Tag @("CI", 'RequireAdminOnWindows') {
It "Get-Help should work in JEA sessions" -Pending {
BeforeAll {
$originalDefaultParameterValues = $PSDefaultParameterValues.Clone()
if ( ! $IsWindows )
{
$PSDefaultParameterValues["it:skip"] = $true
}
else
{
Enable-PSRemoting -SkipNetworkProfileCheck
}
}
AfterAll {
$global:PSDefaultParameterValues = $originalDefaultParameterValues
}
It "Get-Help should work in JEA sessions" {
[string] $RoleCapDirectory = (New-Item -Path "$TestDrive\RoleCapability" -ItemType Directory -Force).FullName
[string] $PSSessionConfigFile = "$RoleCapDirectory\TestConfig.pssc"
try
{
New-PSSessionConfigurationFile -Path $PSSessionConfigFile -TranscriptDirectory $RoleCapDirectory -SessionType RestrictedRemoteServer
Register-PSSessionConfiguration -Name JEA -Path $PSSessionConfigFile -Force -ErrorAction SilentlyContinue
$scriptBlock = {Enter-PSSession -ComputerName Localhost -ConfigurationName JEA; Get-Help Get-Command; Exit-PSSession}
$helpContent = & $scriptBlock
$helpContent | Should Not Be $null
Register-PSSessionConfiguration -Name JEA -Path $PSSessionConfigFile -Force -ErrorAction SilentlyContinue
$scriptBlock = {Enter-RemoteSession -ComputerName Localhost -ConfigurationName JEA; Get-Help Get-Command; Exit-PSSession}
# Invoke the script block in a different PowerShell instance so that when TestDrive tries to delete $RoleCapDirectory,
# the transcription has finished and the files are not locked.
$helpContent = [powershell]::Create().AddScript($scriptBlock).Invoke()
$helpContent | Should Not Be $null
}
finally
{
@ -52,5 +88,195 @@ Describe "JEA session Get-Help test" -Tag @("CI", 'RequireAdminOnWindows') {
Remove-Item $RoleCapDirectory -Recurse -Force -ErrorAction SilentlyContinue
}
}
}
}
Describe "Remoting loopback tests" -Tags @('CI', 'RequireAdminOnWindows') {
BeforeAll {
$originalDefaultParameterValues = $PSDefaultParameterValues.Clone()
if ( ! $IsWindows )
{
$PSDefaultParameterValues["it:skip"] = $true
}
else
{
Enable-PSRemoting -SkipNetworkProfileCheck
$endPoint = (Get-PSSessionConfiguration -Name "PowerShell.$(${PSVersionTable}.GitCommitId)").Name
$disconnectedSession = New-RemoteSession -ConfigurationName $endPoint -ComputerName localhost | Disconnect-PSSession
$closedSession = New-RemoteSession -ConfigurationName $endPoint -ComputerName localhost
$closedSession.Runspace.Close()
$openSession = New-RemoteSession -ConfigurationName $endPoint
$ParameterError = @(
@{
parameters = @{
'InDisconnectedSession' = $true
'AsJob' = $true
'ScriptBlock' = {1}
'ComputerName' = 'localhost'
'ConfigurationName' = $endpoint
}
expectedError = 'System.InvalidOperationException,Microsoft.PowerShell.Commands.InvokeCommandCommand'
title = 'Cannot use InDisconnectedState and AsJob together'
},
@{
parameters = @{
'ScriptBlock' = {1}
'SessionName' = 'SomeSessionName'
}
expectedError = 'System.InvalidOperationException,Microsoft.PowerShell.Commands.InvokeCommandCommand'
title = 'Cannot use SessionName without InDisconnectedSession'
},
@{
parameters = @{
'ScriptBlock' = { 1 }
'Session' = $disconnectedSession
'ErrorAction' = 'Stop'
}
expectedError = 'InvokeCommandCommandInvalidSessionState,Microsoft.PowerShell.Commands.InvokeCommandCommand'
title = 'Cannot use Invoke-Command on a disconnected session'
}
@{
parameters = @{
'ScriptBlock' = { 1 }
'Session' = $closedSession
'ErrorAction' = 'Stop'
}
expectedError = 'InvokeCommandCommandInvalidSessionState,Microsoft.PowerShell.Commands.InvokeCommandCommand'
title = 'Cannot use Invoke-Command on a closed session'
}
)
function script:ValidateSessionInfo($session, $state)
{
$session.ComputerName | Should BeExactly 'localhost'
$session.ConfigurationName | Should BeExactly $endPoint
$session.State | Should Be $state
}
}
}
AfterAll {
$global:PSDefaultParameterValues = $originalDefaultParameterValues
if($isWindows)
{
Remove-PSSession $disconnectedSession,$closedSession,$openSession -ErrorAction SilentlyContinue
}
}
It 'Can connect to default endpoint' {
$session = New-RemoteSession -ConfigurationName $endPoint
try
{
ValidateSessionInfo -session $session -state 'Opened'
}
finally
{
$session | Remove-PSSession -ErrorAction SilentlyContinue
}
}
It 'Can execute command in a disconnected session' {
$session = Invoke-RemoteCommand -InDisconnectedSession -ComputerName 'localhost' -ScriptBlock { 1 + 1 } -ConfigurationName $endPoint
try
{
ValidateSessionInfo -session $session -state 'Disconnected'
$result = Receive-PSSession -Session $session
$result | Should Be 2
$result.PSComputerName | Should BeExactly 'localhost'
}
finally
{
$session | Remove-PSSession -ErrorAction SilentlyContinue
}
}
It 'Can disconnect and connect to PSSession' {
$session = New-RemoteSession -ConfigurationName $endPoint
try
{
ValidateSessionInfo -session $session -state 'Opened'
Disconnect-PSSession -Session $session
ValidateSessionInfo -session $session -state 'Disconnected'
Connect-RemoteSession -Session $session
$result = Invoke-Command -Session $session -ScriptBlock { 1 + 1 }
$result | Should Be 2
$result.PSComputerName | Should BeExactly 'localhost'
}
finally
{
$session | Remove-PSSession -ErrorAction SilentlyContinue
}
}
It "<title>" -TestCases $ParameterError {
param($parameters, $expectedError)
{ Invoke-Command @parameters } | ShouldBeErrorId $expectedError
}
It 'Can execute command if one of the sessions is available' {
try
{
$result = Invoke-Command -Session $openSession,$disconnectedSession,$closedSession -ScriptBlock { 1+1 } -ErrorAction SilentlyContinue
}
catch
{
if($_.FullyQualifiedErrorId -ne 'InvokeCommandCommandInvalidSessionState,Microsoft.PowerShell.Commands.InvokeCommandCommand')
{
# We expect the error from $disconnectedSession and $closedSession. Hence, throw otherwise.
throw $_
}
}
$result.Count | Should Be 1
$result | Should Be 2
}
It 'Can execute command without creating new scope' {
Invoke-Command -NoNewScope -ScriptBlock { $sameScopeVariable = 'SetInCurrentScope' }
$sameScopeVariable | Should BeExactly 'SetInCurrentScope'
}
It 'Can execute command from a file' {
$fileName = "$testdrive/remotingscript.ps1"
'1 + 1' | Out-File $fileName
$result = Invoke-Command -FilePath $fileName -Session $openSession
$result | Should Be 2
}
It 'Can invoke-command as job' {
$result = Invoke-Command -ScriptBlock { 1 + 1 } -Session $openSession -AsJob | Receive-Job -AutoRemoveJob -Wait
$result | Should Be 2
}
It 'Can connect to all disconnected sessions by name' {
$connectionNames = @("DiscPSS$(Get-Random)", "DiscPSS$(Get-Random)")
$connectionNames | ForEach-Object { $null = New-RemoteSession -ComputerName localhost -ConfigurationName $endpoint -Name $_ | Disconnect-PSSession}
Connect-RemoteSession -ComputerName localhost -Name $connectionNames -ConfigurationName $endpoint
$sessions = Get-PSSession -Name $connectionNames
try
{
$sessions | ForEach-Object {
ValidateSessionInfo -session $_ -state 'Opened'
}
}
finally
{
$sessions | Remove-PSSession -ErrorAction SilentlyContinue
}
}
It 'Can pass values through $using' {
$number = 100
$result = Invoke-Command -Session $openSession -ScriptBlock { $using:number }
$result | Should Be 100
}
}

View file

@ -16,6 +16,6 @@ Copyright = 'Copyright (C) Microsoft Corporation, All rights reserved.'
Description = 'Temporary module for remoting tests'
FunctionsToExport = 'New-RemoteRunspace', 'New-RemoteSession'
FunctionsToExport = 'New-RemoteRunspace', 'New-RemoteSession', 'Enter-RemoteSession', 'Invoke-RemoteCommand', 'Connect-RemoteSession'
}

View file

@ -8,7 +8,6 @@ if ($IsWindows) {
try { $Script:AppVeyorRemoteCred = Import-Clixml -Path "$env:TEMP\AppVeyorRemoteCred.xml" } catch { }
}
function New-RemoteRunspace
{
$wsmanConInfo = [System.Management.Automation.Runspaces.WSManConnectionInfo]::new()
@ -29,16 +28,30 @@ function New-RemoteRunspace
return $remoteRunspace
}
function New-RemoteSession
function CreateParameters
{
param (
[string] $Name,
[string] $ComputerName,
[string[]] $Name,
[string] $ConfigurationName,
[switch] $CimSession,
[System.Management.Automation.Remoting.PSSessionOption] $SessionOption)
[System.Management.Automation.Remoting.PSSessionOption] $SessionOption,
[System.Management.Automation.Runspaces.PSSession[]] $Session)
$parameters = @{ ComputerName = "."; }
if($ComputerName)
{
$parameters = @{ComputerName = $ComputerName}
}
else
{
if($Session)
{
$parameters = @{Session = $Session}
}
else
{
$parameters = @{ComputerName = '.'}
}
}
if ($Name) {
$parameters["Name"] = $Name
@ -52,7 +65,8 @@ function New-RemoteSession
$parameters["SessionOption"] = $SessionOption
}
if ($Script:AppVeyorRemoteCred)
## If a PSSession is provided, do not add credentials.
if ($Script:AppVeyorRemoteCred -and (-not $Session))
{
Write-Verbose "Using Global AppVeyor Credential" -Verbose
$parameters["Credential"] = $Script:AppVeyorRemoteCred
@ -62,6 +76,18 @@ function New-RemoteSession
Write-Verbose "Using Implicit Credential" -Verbose
}
return $parameters
}
function New-RemoteSession
{
param (
[string] $Name,
[string] $ConfigurationName,
[switch] $CimSession,
[System.Management.Automation.Remoting.PSSessionOption] $SessionOption)
$parameters = CreateParameters -Name $Name -ConfigurationName $ConfigurationName -SessionOption $SessionOption
if ($CimSession) {
$session = New-CimSession @parameters
} else {
@ -70,3 +96,50 @@ function New-RemoteSession
return $session
}
function Invoke-RemoteCommand
{
param (
[string] $ComputerName,
[scriptblock] $ScriptBlock,
[string] $ConfigurationName,
[switch] $InDisconnectedSession)
$parameters = CreateParameters -ComputerName $ComputerName -ConfigurationName $ConfigurationName
if($ScriptBlock)
{
$parameters.Add('ScriptBlock', $ScriptBlock)
}
if($InDisconnectedSession)
{
$parameters.Add('InDisconnectedSession', $InDisconnectedSession.IsPresent)
}
Invoke-Command @parameters
}
function Enter-RemoteSession
{
param(
[string] $Name,
[string] $ConfigurationName,
[System.Management.Automation.Remoting.PSSessionOption] $SessionOption)
$parameters = CreateParameters -Name $Name -ConfigurationName $ConfigurationName -SessionOption $SessionOption
Enter-PSSession @parameters
}
function Connect-RemoteSession
{
param(
[string] $ComputerName,
[string[]] $Name,
[System.Management.Automation.Runspaces.PSSession[]] $Session,
[string] $ConfigurationName
)
$parameters = CreateParameters -ComputerName $ComputerName -Name $Name -Session $Session -ConfigurationName $ConfigurationName
Connect-PSSession @parameters
}