В PowerShell передать сложный объект (SmoServer) фоновому заданию в ArgumentList - застрял в «NotStarted» - PullRequest
0 голосов
/ 27 сентября 2018

Я пытаюсь передать предварительно созданный объект SmoServer в фоновое задание, чтобы распараллелить некоторые операции с несколькими серверами SQL.Однако, когда я пытаюсь сделать это, дочернее задание вызванного задания застревает в состоянии «NotStarted».Очень простой тест:

[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO")
$SmoServer = New-Object Microsoft.SqlServer.Management.Smo.Server MySqlServer
Start-Job -Name Test -ScriptBlock {
    param($SmoServer) 
    $SmoServer.Databases.Name 
} -InitializationScript {
    [void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO"); Import-Module SQLPS -DisableNameChecking
} -ArgumentList $SmoServer

Задание начинается, но ChildJob застревает "NotStarted"

PS C:\Users\omrsafetyo> Get-Job Test

Id     Name            PSJobTypeName   State         HasMoreData     Location             Command
--     ----            -------------   -----         -----------     --------             -------
5      Test            BackgroundJob   Running       True            localhost            param($SmoServer) $Smo...


PS C:\Users\omrsafetyo> Get-Job Test | select -expand childjobs

Id     Name            PSJobTypeName   State         HasMoreData     Location             Command
--     ----            -------------   -----         -----------     --------             -------
6      Job6                            NotStarted    True            localhost            param($SmoServer) $Smo...

Я сталкивался с этим некоторое время назад и никогда не нашел решения.А потом я наткнулся на -IntializationScript и подумал, что это может быть серебряная пуля.Кажется, это не так.

То же самое относится и к Invoke-Command.Если я просто запускаю Invoke-Command, команда работает нормально.Однако, если я запускаю Invoke-Command -AsJob и пропускаю объект SmoServer, он все равно не работает.

Как передать эти сложные объекты, для которых требуется сборка / модуль, загруженный в ArgumentList, в фоновое задание?

1 Ответ

0 голосов
/ 27 сентября 2018

Задания PowerShell запускаются в отдельном процессе, а объекты, передаваемые в качестве аргументов, сериализуются (с помощью чего-то вроде Export-CliXml или морального эквивалента).Когда ваш объект «регидратируется» в фоновом процессе, он больше не будет экземпляром Microsoft.SqlServer.Management.Smo.Server, а скорее просто объектом, который выглядит как один (он будет иметь те же свойства, какими они былисериализуется в исходном процессе).

Вы можете передавать объекты .NET в разные пространства выполнения в рамках одного и того же процесса.Простой способ сделать это - использовать модуль PSThreadJob .

Эксперимент, демонстрирующий, что происходит с объектами, передаваемыми в фоновые задания:

$srcFi = [System.IO.FileInfo]::new( 'C:\windows\system32\ntdll.dll' )
$srcFi.GetType().FullName
start-job -ScriptBlock { param( $fi ) $fi.GetType().FullName } -Arg @( $srcFi ) | Receive-Job -Wait

Вывод:

System.IO.FileInfo
System.Management.Automation.PSObject
...