在PowerShell中,将复杂对象(SmoServer)传递到ArgumentList中的后台作业-卡在“ NotStarted”中

时间:2018-09-27 16:44:16

标签: powershell smo

我正在尝试将预先构建的SmoServer对象传递给后台作业,以并行处理针对多个SQL Server的某些操作。但是,当我尝试执行此操作时,被调用作业的“子”作业被卡在“未启动”状态。一个非常基本的测试:

[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卡住了“未启动”

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 :(得分:0)

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