mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Add ThreadJob module package and tests (#7169)
This commit is contained in:
committed by
Travis Plunk
parent
73d71d9a9c
commit
a57fafedc6
@@ -1825,6 +1825,16 @@
|
||||
</Directory>
|
||||
</Directory>
|
||||
</Directory>
|
||||
<Directory Id="dir37EBACBC570E49108415C3BA316EB66D" Name="ThreadJob">
|
||||
<Directory Id="dirCB93DAC4CEB64A8583295B9AC4A79883" Name="1.1.1">
|
||||
<Component Id="cmp9ADDEE83EFD3497C804FDC6B93A58031" Guid="{9ADDEE83EFD3497C804FDC6B93A58031}">
|
||||
<File Id="fil15E1EF74BF8C4AFFA6E9B53D8CF6E15E" KeyPath="yes" Source="$(env.ProductSourcePath)\Modules\ThreadJob\1.1.1\ThreadJob.dll" />
|
||||
</Component>
|
||||
<Component Id="cmp57A7DBFA4541443CB3AB8A4B82DB53E0" Guid="{57A7DBFA4541443CB3AB8A4B82DB53E0}">
|
||||
<File Id="fil57D698A50A2A40E58B0B954F55AEEA37" KeyPath="yes" Source="$(env.ProductSourcePath)\Modules\ThreadJob\1.1.1\ThreadJob.psd1" />
|
||||
</Component>
|
||||
</Directory>
|
||||
</Directory>
|
||||
<Directory Id="dirECE37E3EC3637A365744D075BD8132E9" Name="Microsoft.PowerShell.Management">
|
||||
<Component Id="cmp6DAFD01CAA3A4C67185922F445EDE495" Guid="{D4374EC0-26FC-4607-AF6B-35721698E8A5}">
|
||||
<File Id="fil92C4A6B2083E49B1909D17BC06E7526F" KeyPath="yes" Source="$(env.ProductSourcePath)\Modules\Microsoft.PowerShell.Management\Microsoft.PowerShell.Management.psd1" />
|
||||
@@ -2195,6 +2205,8 @@
|
||||
<ComponentRef Id="cmpEC5CF579D39FC75DC38E051E55A5CAD5" />
|
||||
<ComponentRef Id="cmp0B896DBA6AFF2FD27FCD0E0968E23992" />
|
||||
<ComponentRef Id="cmpC6A24F97E0D6739A51FE9CC80148F511" />
|
||||
<ComponentRef Id="cmp9ADDEE83EFD3497C804FDC6B93A58031" />
|
||||
<ComponentRef Id="cmp57A7DBFA4541443CB3AB8A4B82DB53E0" />
|
||||
<ComponentRef Id="cmp5E6D0C75A767F360277D22D90E4689FF" />
|
||||
<ComponentRef Id="cmp9544B34C5A30F75D0F45F5718A1795F0" />
|
||||
<ComponentRef Id="cmpBDF0DC73F4F799A46B1DE220E58C1920" />
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<PackageReference Include="PowerShellGet" Version="1.6.0" />
|
||||
<PackageReference Include="Microsoft.PowerShell.Archive" Version="1.1.0.0" />
|
||||
<PackageReference Include="PSReadLine" Version="2.0.0-beta2" />
|
||||
<PackageReference Include="ThreadJob" Version="1.1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
+72
@@ -645,6 +645,78 @@ try
|
||||
}
|
||||
}
|
||||
|
||||
Describe "ThreadJob Constrained Language Tests" -Tags 'Feature','RequireAdminOnWindows' {
|
||||
|
||||
BeforeAll {
|
||||
|
||||
$sb = { $ExecutionContext.SessionState.LanguageMode }
|
||||
}
|
||||
|
||||
It "ThreadJob script must run in ConstrainedLanguage mode with system lock down" {
|
||||
|
||||
try
|
||||
{
|
||||
$ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"
|
||||
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
|
||||
|
||||
$results = Start-ThreadJob -ScriptBlock { $ExecutionContext.SessionState.LanguageMode } | Wait-Job | Receive-Job
|
||||
$results | Should BeExactly "ConstrainedLanguage"
|
||||
}
|
||||
finally
|
||||
{
|
||||
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
|
||||
}
|
||||
}
|
||||
|
||||
It "ThreadJob script block using variable must run in ConstrainedLanguage mode with system lock down" {
|
||||
|
||||
try
|
||||
{
|
||||
$ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"
|
||||
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
|
||||
|
||||
$results = Start-ThreadJob -ScriptBlock { & $using:sb } | Wait-Job | Receive-Job
|
||||
$results | Should BeExactly "ConstrainedLanguage"
|
||||
}
|
||||
finally
|
||||
{
|
||||
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
|
||||
}
|
||||
}
|
||||
|
||||
It "ThreadJob script block argument variable must run in ConstrainedLanguage mode with system lock down" {
|
||||
|
||||
try
|
||||
{
|
||||
$ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"
|
||||
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
|
||||
|
||||
$results = Start-ThreadJob -ScriptBlock { param ($sb) & $sb } -ArgumentList $sb | Wait-Job | Receive-Job
|
||||
$results | Should BeExactly "ConstrainedLanguage"
|
||||
}
|
||||
finally
|
||||
{
|
||||
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
|
||||
}
|
||||
}
|
||||
|
||||
It "ThreadJob script block piped variable must run in ConstrainedLanguage mode with system lock down" {
|
||||
|
||||
try
|
||||
{
|
||||
$ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"
|
||||
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
|
||||
|
||||
$results = $sb | Start-ThreadJob -ScriptBlock { $input | foreach { & $_ } } | Wait-Job | Receive-Job
|
||||
$results | Should BeExactly "ConstrainedLanguage"
|
||||
}
|
||||
finally
|
||||
{
|
||||
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# End Describe blocks
|
||||
}
|
||||
finally
|
||||
|
||||
@@ -0,0 +1,373 @@
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
Describe 'Basic ThreadJob Tests' -Tags 'CI' {
|
||||
|
||||
BeforeAll {
|
||||
|
||||
$scriptFilePath1 = Join-Path $testdrive "TestThreadJobFile1.ps1"
|
||||
@'
|
||||
for ($i=0; $i -lt 10; $i++)
|
||||
{
|
||||
Write-Output "Hello $i"
|
||||
}
|
||||
'@ > $scriptFilePath1
|
||||
|
||||
$scriptFilePath2 = Join-Path $testdrive "TestThreadJobFile2.ps1"
|
||||
@'
|
||||
param ($arg1, $arg2)
|
||||
Write-Output $arg1
|
||||
Write-Output $arg2
|
||||
'@ > $scriptFilePath2
|
||||
|
||||
$scriptFilePath3 = Join-Path $testdrive "TestThreadJobFile3.ps1"
|
||||
@'
|
||||
$input | foreach {
|
||||
Write-Output $_
|
||||
}
|
||||
'@ > $scriptFilePath3
|
||||
|
||||
$scriptFilePath4 = Join-Path $testdrive "TestThreadJobFile4.ps1"
|
||||
@'
|
||||
Write-Output $using:Var1
|
||||
Write-Output $($using:Array1)[2]
|
||||
Write-Output @(,$using:Array1)
|
||||
'@ > $scriptFilePath4
|
||||
|
||||
$scriptFilePath5 = Join-Path $testdrive "TestThreadJobFile5.ps1"
|
||||
@'
|
||||
param ([string]$param1)
|
||||
Write-Output "$param1 $using:Var1 $using:Var2"
|
||||
'@ > $scriptFilePath5
|
||||
}
|
||||
|
||||
AfterEach {
|
||||
Get-Job | where PSJobTypeName -eq "ThreadJob" | Remove-Job -Force
|
||||
}
|
||||
|
||||
It 'ThreadJob with ScriptBlock' {
|
||||
|
||||
$job = Start-ThreadJob -ScriptBlock { "Hello" }
|
||||
$results = $job | Receive-Job -Wait
|
||||
$results | Should -Be "Hello"
|
||||
}
|
||||
|
||||
It 'ThreadJob with ScriptBlock and Initialization script' {
|
||||
|
||||
$job = Start-ThreadJob -ScriptBlock { "Goodbye" } -InitializationScript { "Hello" }
|
||||
$results = $job | Receive-Job -Wait
|
||||
$results[0] | Should -Be "Hello"
|
||||
$results[1] | Should -Be "Goodbye"
|
||||
}
|
||||
|
||||
It 'ThreadJob with ScriptBlock and Argument list' {
|
||||
|
||||
$job = Start-ThreadJob -ScriptBlock { param ($arg1, $arg2) $arg1; $arg2 } -ArgumentList @("Hello","Goodbye")
|
||||
$results = $job | Receive-Job -Wait
|
||||
$results[0] | Should -Be "Hello"
|
||||
$results[1] | Should -Be "Goodbye"
|
||||
}
|
||||
|
||||
It 'ThreadJob with ScriptBlock and piped input' {
|
||||
|
||||
$job = "Hello","Goodbye" | Start-ThreadJob -ScriptBlock { $input | foreach { $_ } }
|
||||
$results = $job | Receive-Job -Wait
|
||||
$results[0] | Should -Be "Hello"
|
||||
$results[1] | Should -Be "Goodbye"
|
||||
}
|
||||
|
||||
It 'ThreadJob with ScriptBlock and Using variables' {
|
||||
|
||||
$Var1 = "Hello"
|
||||
$Var2 = "Goodbye"
|
||||
$Var3 = 102
|
||||
$Var4 = 1..5
|
||||
$global:GVar1 = "GlobalVar"
|
||||
$job = Start-ThreadJob -ScriptBlock {
|
||||
Write-Output $using:Var1
|
||||
Write-Output $using:Var2
|
||||
Write-Output $using:Var3
|
||||
Write-Output ($using:Var4)[1]
|
||||
Write-Output @(,$using:Var4)
|
||||
Write-Output $using:GVar1
|
||||
}
|
||||
|
||||
$results = $job | Receive-Job -Wait
|
||||
$results[0] | Should -Be $Var1
|
||||
$results[1] | Should -Be $Var2
|
||||
$results[2] | Should -Be $Var3
|
||||
$results[3] | Should -Be 2
|
||||
$results[4] | Should -Be $Var4
|
||||
$results[5] | Should -Be $global:GVar1
|
||||
}
|
||||
|
||||
It 'ThreadJob with ScriptBlock and Using variables and argument list' {
|
||||
|
||||
$Var1 = "Hello"
|
||||
$Var2 = 52
|
||||
$job = Start-ThreadJob -ScriptBlock {
|
||||
param ([string] $param1)
|
||||
|
||||
"$using:Var1 $param1 $using:Var2"
|
||||
} -ArgumentList "There"
|
||||
|
||||
$results = $job | Receive-Job -Wait
|
||||
$results | Should -Be "Hello There 52"
|
||||
}
|
||||
|
||||
It 'ThreadJob with ScriptFile' {
|
||||
|
||||
$job = Start-ThreadJob -FilePath $scriptFilePath1
|
||||
$results = $job | Receive-Job -Wait
|
||||
$results.Count | Should -Be 10
|
||||
$results[9] | Should -Be "Hello 9"
|
||||
}
|
||||
|
||||
It 'ThreadJob with ScriptFile and Initialization script' {
|
||||
|
||||
$job = Start-ThreadJob -FilePath $scriptFilePath1 -Initialization { "Goodbye" }
|
||||
$results = $job | Receive-Job -Wait
|
||||
$results.Count | Should -Be 11
|
||||
$results[0] | Should -Be "Goodbye"
|
||||
}
|
||||
|
||||
It 'ThreadJob with ScriptFile and Argument list' {
|
||||
|
||||
$job = Start-ThreadJob -FilePath $scriptFilePath2 -ArgumentList @("Hello","Goodbye")
|
||||
$results = $job | Receive-Job -Wait
|
||||
$results[0] | Should -Be "Hello"
|
||||
$results[1] | Should -Be "Goodbye"
|
||||
}
|
||||
|
||||
It 'ThreadJob with ScriptFile and piped input' {
|
||||
|
||||
$job = "Hello","Goodbye" | Start-ThreadJob -FilePath $scriptFilePath3
|
||||
$results = $job | Receive-Job -Wait
|
||||
$results[0] | Should -Be "Hello"
|
||||
$results[1] | Should -Be "Goodbye"
|
||||
}
|
||||
|
||||
It 'ThreadJob with ScriptFile and Using variables' {
|
||||
|
||||
$Var1 = "Hello!"
|
||||
$Array1 = 1..10
|
||||
|
||||
$job = Start-ThreadJob -FilePath $scriptFilePath4
|
||||
$results = $job | Receive-Job -Wait
|
||||
$results[0] | Should -Be $Var1
|
||||
$results[1] | Should -Be 3
|
||||
$results[2] | Should -Be $Array1
|
||||
}
|
||||
|
||||
It 'ThreadJob with ScriptFile and Using variables with argument list' {
|
||||
|
||||
$Var1 = "There"
|
||||
$Var2 = 60
|
||||
$job = Start-ThreadJob -FilePath $scriptFilePath5 -ArgumentList "Hello"
|
||||
$results = $job | Receive-Job -Wait
|
||||
$results | Should -Be "Hello There 60"
|
||||
}
|
||||
|
||||
It 'ThreadJob with terminating error' {
|
||||
|
||||
$job = Start-ThreadJob -ScriptBlock { throw "MyError!" }
|
||||
$job | Wait-Job
|
||||
$job.JobStateInfo.Reason.Message | Should -Be "MyError!"
|
||||
}
|
||||
|
||||
It 'ThreadJob and Error stream output' {
|
||||
|
||||
$job = Start-ThreadJob -ScriptBlock { Write-Error "ErrorOut" } | Wait-Job
|
||||
$job.Error | Should -Be "ErrorOut"
|
||||
}
|
||||
|
||||
It 'ThreadJob and Warning stream output' {
|
||||
|
||||
$job = Start-ThreadJob -ScriptBlock { Write-Warning "WarningOut" } | Wait-Job
|
||||
$job.Warning | Should -Be "WarningOut"
|
||||
}
|
||||
|
||||
It 'ThreadJob and Verbose stream output' {
|
||||
|
||||
$job = Start-ThreadJob -ScriptBlock { $VerbosePreference = 'Continue'; Write-Verbose "VerboseOut" } | Wait-Job
|
||||
$job.Verbose | Should Match "VerboseOut"
|
||||
}
|
||||
|
||||
It 'ThreadJob and Verbose stream output' {
|
||||
|
||||
$job = Start-ThreadJob -ScriptBlock { $DebugPreference = 'Continue'; Write-Debug "DebugOut" } | Wait-Job
|
||||
$job.Debug | Should -Be "DebugOut"
|
||||
}
|
||||
|
||||
It 'ThreadJob ThrottleLimit and Queue' {
|
||||
|
||||
try
|
||||
{
|
||||
# Start four thread jobs with ThrottleLimit set to two
|
||||
Get-Job | where PSJobTypeName -eq "ThreadJob" | Remove-Job -Force
|
||||
Start-ThreadJob -ScriptBlock { Start-Sleep -Seconds 60 } -ThrottleLimit 2
|
||||
Start-ThreadJob -ScriptBlock { Start-Sleep -Seconds 60 }
|
||||
Start-ThreadJob -ScriptBlock { Start-Sleep -Seconds 60 }
|
||||
Start-ThreadJob -ScriptBlock { Start-Sleep -Seconds 60 }
|
||||
|
||||
# Allow jobs to start
|
||||
Start-Sleep -Seconds 1
|
||||
|
||||
$numRunningThreadJobs = (Get-Job | where { ($_.PSJobTypeName -eq "ThreadJob") -and ($_.State -eq "Running") }).Count
|
||||
$numQueuedThreadJobs = (Get-Job | where { ($_.PSJobTypeName -eq "ThreadJob") -and ($_.State -eq "NotStarted") }).Count
|
||||
|
||||
$numRunningThreadJobs | Should -Be 2
|
||||
$numQueuedThreadJobs | Should -Be 2
|
||||
}
|
||||
finally
|
||||
{
|
||||
Get-Job | where PSJobTypeName -eq "ThreadJob" | Remove-Job -Force
|
||||
}
|
||||
|
||||
$numThreadJobs = (Get-Job | where PSJobTypeName -eq "ThreadJob").Count
|
||||
$numThreadJobs | Should -Be 0
|
||||
}
|
||||
|
||||
It 'ThreadJob Runspaces should be cleaned up at completion' {
|
||||
|
||||
try
|
||||
{
|
||||
Get-Job | where PSJobTypeName -eq "ThreadJob" | Remove-Job -Force
|
||||
$rsStartCount = (Get-Runspace).Count
|
||||
|
||||
# Start four thread jobs with ThrottleLimit set to two
|
||||
$Job1 = Start-ThreadJob -ScriptBlock { "Hello 1!" } -ThrottleLimit 5
|
||||
$job2 = Start-ThreadJob -ScriptBlock { "Hello 2!" }
|
||||
$job3 = Start-ThreadJob -ScriptBlock { "Hello 3!" }
|
||||
$job4 = Start-ThreadJob -ScriptBlock { "Hello 4!" }
|
||||
|
||||
$job1,$job2,$job3,$job4 | Wait-Job
|
||||
|
||||
# Allow for clean to happen
|
||||
Start-Sleep -Seconds 1
|
||||
|
||||
(Get-Runspace).Count | Should -Be $rsStartCount
|
||||
}
|
||||
finally
|
||||
{
|
||||
Get-Job | where PSJobTypeName -eq "ThreadJob" | Remove-Job -Force
|
||||
}
|
||||
}
|
||||
|
||||
It 'ThreadJob Runspaces should be cleaned up after job removal' {
|
||||
|
||||
try {
|
||||
Get-Job | where PSJobTypeName -eq "ThreadJob" | Remove-Job -Force
|
||||
$rsStartCount = (Get-Runspace).Count
|
||||
|
||||
# Start four thread jobs with ThrottleLimit set to two
|
||||
$Job1 = Start-ThreadJob -ScriptBlock { Start-Sleep -Seconds 60 } -ThrottleLimit 2
|
||||
$job2 = Start-ThreadJob -ScriptBlock { Start-Sleep -Seconds 60 }
|
||||
$job3 = Start-ThreadJob -ScriptBlock { Start-Sleep -Seconds 60 }
|
||||
$job4 = Start-ThreadJob -ScriptBlock { Start-Sleep -Seconds 60 }
|
||||
|
||||
# Allow jobs to start
|
||||
Start-Sleep -Seconds 1
|
||||
|
||||
(Get-Runspace).Count | Should -Be ($rsStartCount + 4)
|
||||
|
||||
# Stop two jobs
|
||||
$job1 | Remove-Job -Force
|
||||
$job3 | Remove-Job -Force
|
||||
|
||||
(Get-Runspace).Count | Should -Be ($rsStartCount + 2)
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
Get-Job | where PSJobTypeName -eq "ThreadJob" | Remove-Job -Force
|
||||
}
|
||||
|
||||
(Get-Runspace).Count | Should -Be $rsStartCount
|
||||
}
|
||||
|
||||
It 'ThreadJob jobs should work with Receive-Job -AutoRemoveJob' {
|
||||
|
||||
Get-Job | where PSJobTypeName -eq "ThreadJob" | Remove-Job -Force
|
||||
|
||||
$job1 = Start-ThreadJob -ScriptBlock { 1..2 | foreach { Start-Sleep -Seconds 1; "Output $_" } } -ThrottleLimit 2
|
||||
$job2 = Start-ThreadJob -ScriptBlock { 1..2 | foreach { Start-Sleep -Seconds 1; "Output $_" } }
|
||||
$job3 = Start-ThreadJob -ScriptBlock { 1..2 | foreach { Start-Sleep -Seconds 1; "Output $_" } }
|
||||
$job4 = Start-ThreadJob -ScriptBlock { 1..2 | foreach { Start-Sleep -Seconds 1; "Output $_" } }
|
||||
|
||||
$null = $job1,$job2,$job3,$job4 | Receive-Job -Wait -AutoRemoveJob
|
||||
|
||||
(Get-Job | where PSJobTypeName -eq "ThreadJob").Count | Should -Be 0
|
||||
}
|
||||
|
||||
It 'ThreadJob jobs should run in FullLanguage mode by default' {
|
||||
|
||||
$result = Start-ThreadJob -ScriptBlock { $ExecutionContext.SessionState.LanguageMode } | Wait-Job | Receive-Job
|
||||
$result | Should -Be "FullLanguage"
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'Job2 class API tests' -Tags 'CI' {
|
||||
|
||||
AfterEach {
|
||||
Get-Job | where PSJobTypeName -eq "ThreadJob" | Remove-Job -Force
|
||||
}
|
||||
|
||||
It 'Verifies StopJob API' {
|
||||
|
||||
$job = Start-ThreadJob -ScriptBlock { Start-Sleep -Seconds 60 } -ThrottleLimit 5
|
||||
$job.StopJob($true, "No Reason")
|
||||
$job.JobStateInfo.State | Should -Be "Stopped"
|
||||
}
|
||||
|
||||
It 'Verifies StopJobAsync API' {
|
||||
|
||||
$job = Start-ThreadJob -ScriptBlock { Start-Sleep -Seconds 60 } -ThrottleLimit 5
|
||||
$job.StopJobAsync($true, "No Reason")
|
||||
Wait-Job $job
|
||||
$job.JobStateInfo.State | Should -Be "Stopped"
|
||||
}
|
||||
|
||||
It 'Verifies StartJobAsync API' {
|
||||
|
||||
$jobRunning = Start-ThreadJob -ScriptBlock { Start-Sleep -Seconds 60 } -ThrottleLimit 1
|
||||
$jobNotRunning = Start-ThreadJob -ScriptBlock { Start-Sleep -Seconds 60 }
|
||||
|
||||
$jobNotRunning.JobStateInfo.State | Should -Be "NotStarted"
|
||||
|
||||
# StartJobAsync starts jobs synchronously for ThreadJob jobs
|
||||
$jobNotRunning.StartJobAsync()
|
||||
$jobNotRunning.JobStateInfo.State | Should -Be "Running"
|
||||
}
|
||||
|
||||
It 'Verifies JobSourceAdapter Get-Jobs' {
|
||||
|
||||
$job = Start-ThreadJob -ScriptBlock { "Hello" } | Wait-Job
|
||||
|
||||
$getJob = Get-Job -InstanceId $job.InstanceId 2>$null
|
||||
$getJob | Should -Be $job
|
||||
|
||||
$getJob = Get-Job -Name $job.Name 2>$null
|
||||
$getJob | Should -Be $job
|
||||
|
||||
$getJob = Get-Job -Command ' "hello" ' 2>$null
|
||||
$getJob | Should -Be $job
|
||||
|
||||
$getJob = Get-Job -State $job.JobStateInfo.State 2>$null
|
||||
$getJob | Should -Be $job
|
||||
|
||||
$getJob = Get-Job -Id $job.Id 2>$null
|
||||
$getJob | Should -Be $job
|
||||
|
||||
# Get-Job -Filter is not supported
|
||||
$result = Get-Job -Filter @{Id = ($job.Id)} 3>$null
|
||||
$result | Should -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Verifies terminating job error' {
|
||||
|
||||
$job = Start-ThreadJob -ScriptBlock { throw "My Job Error!" } | Wait-Job
|
||||
$results = $job | Receive-Job 2>&1
|
||||
$results.ToString() | Should -Be "My Job Error!"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user