Открытие пула Runspace с использованием пользовательских классов (C #) выдает ошибку - PullRequest
0 голосов
/ 05 мая 2018

Мне нужно добавить возможности многопоточности в скрипт PowerShell. К сожалению, я получаю сообщение об ошибке при попытке открыть пул пространства выполнения с помощью пользовательских классов C # в объекте InitialSessionState. В следующем примере приведен только код DEMO, а не оригинальный скрипт. Вы можете скопировать и вставить его, и он будет работать без каких-либо изменений, необходимых. Что действительно странно, так это то, что все, кажется, работает правильно, несмотря на сообщение об ошибке, возникающее при открытии пула пространства выполнения.

Это сообщение об ошибке (переведено):

Ошибка при загрузке файла данных расширенного типа: Ошибка в данных типа "FooBar.BarClass": TypeData должно иметь: "Members", "TypeConverters", "TypeAdapters" или "StandardMembers".

Я уже работал и тестировал в течение нескольких часов и понятия не имею, в чем причина этого сообщения. И да, я знаю, что есть очень хорошие библиотеки и командлеты, доступные для многопоточности, но я не могу использовать их по разным причинам.

# Simple c-sharp classes
Add-Type -TypeDef @"
namespace FooBar {
    public class FooClass {
        public string Foo() {
            return "Foo";
        }
    }

    public class BarClass {
        public string Bar() {
            return "Bar";
        }
    }
}
"@

function callFooBar {
    [FooBar.FooClass]$foo = New-Object FooBar.FooClass
    [FooBar.BarClass]$bar = New-Object FooBar.BarClass

    $foo.Foo() + $bar.Bar()
}

$scriptBlock = {
    Write-Output ( callFooBar )
}

# Setting up an initial session state object
$initialSessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()

# Getting the function definition for the functions to add
$functionDefinition = Get-Content function:\callFooBar
$functionEntry = New-Object System.Management.Automation.Runspaces.SessionStateFunctionEntry -ArgumentList 'callFooBar', $functionDefinition

# And add it to the iss object
[void]$initialSessionState.Commands.Add($functionEntry)

# Get the type data for the custom types to add
$typeData = New-Object System.Management.Automation.Runspaces.TypeData -ArgumentList 'FooBar.FooClass'
$typeEntry = New-Object System.Management.Automation.Runspaces.SessionStateTypeEntry -ArgumentList $typeData, $false

# And add it to the iss object
[void]$initialSessionState.Types.Add($typeEntry)

# Get the type data for the custom types to add
$typeData = New-Object System.Management.Automation.Runspaces.TypeData -ArgumentList 'FooBar.BarClass'
$typeEntry = New-Object System.Management.Automation.Runspaces.SessionStateTypeEntry -ArgumentList $typeData, $false

# And add it to the iss object
[void]$initialSessionState.Types.Add($typeEntry)

# Create Runspace pool
$RunspacePool = [RunspaceFactory]::CreateRunspacePool(1, ([int]$env:NUMBER_OF_PROCESSORS + 1), $initialSessionState, $Host)
$RunspacePool.ApartmentState = 'MTA'
[void]$RunspacePool.Open()  # <<<< Error occurs here!

[System.Collections.Generic.List[object]]$Jobs = @()

1..2 | % {
    $job = [System.Management.Automation.PowerShell]::Create($initialSessionState)
    $job.RunspacePool = $RunspacePool
    [void]$job.AddScript($scriptBlock)   
    $jobs += New-Object PSObject -Property @{
        RunNum = $_
        Pipe   = $job
        Result = $job.BeginInvoke()
    }
}

do {
} while ($jobs.Result.IsCompleted -contains $false)
Write-Host "All jobs completed!"

$Results = @()
foreach ($job in $jobs) {
    $Results += $job.Pipe.EndInvoke($job.Result)
}

$Results

$RunspacePool.Close()
$RunspacePool.Dispose()

1 Ответ

0 голосов
/ 06 мая 2018

@ mklement0 Ваш намек ведет меня в правильном направлении! Пользовательские классы C # с определением типа должны быть добавлены в пул runspace другим способом. Теперь это работало (после нескольких часов тестирования со всеми возможными методами runspace ...):

# Get the script data for the custom c# class to add
$scriptDefinition = New-Object System.Management.Automation.Runspaces.ScriptConfigurationEntry -ArgumentList 'FooBar.FooClass', $false
$scriptEntry = New-Object System.Management.Automation.Runspaces.SessionStateScriptEntry -ArgumentList $scriptDefinition

# And add it to the iss object
[void]$initialSessionState.Commands.Add($scriptEntry)

# Get the script data for the custom c# class to add
$scriptDefinition = New-Object System.Management.Automation.Runspaces.ScriptConfigurationEntry -ArgumentList 'FooBar.BarClass', $false
$scriptEntry = New-Object System.Management.Automation.Runspaces.SessionStateScriptEntry -ArgumentList $scriptDefinition

# And add it to the iss object
[void]$initialSessionState.Commands.Add($scriptEntry)

Не по типу, а по сценарию и команде. Спасибо за подсказку.

...