我正在尝试将预先构建的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中预先加载的程序集/模块的这些复杂对象传递给后台作业?
答案 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