我必须为PowerShell脚本添加多线程功能。不幸的是,当我尝试使用InitialSessionState
对象中的自定义C#类打开一个运行空间池时出现错误。以下示例仅是DEMO代码,而不是原始脚本。您可以复制并粘贴它,它将无需任何修改即可运行。真正奇怪的是,尽管在打开运行空间池时出现错误消息,但所有这些似乎都能正常工作。
这是错误消息(已翻译):
加载扩展类型数据文件时出错:类型数据错误" FooBar.BarClass":TypeData必须:"成员"," TypeConverters", " TypeAdapters"或" StandardMembers"。
我已经工作并测试了几个小时,并且不知道该消息的原因是什么。是的,我知道有很好的库和cmdlet可用于多线程,但由于不同的原因我无法使用它们。
# 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()
答案 0 :(得分:2)
@ mklement0你的提示引导我走向正确的方向!必须以与runspacepool不同的方式添加具有类型定义的自定义C#类。这现在正在运行(经过几个小时的测试,使用所有可能的运行空间方法......):
# 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)
不是按类型,而是使用脚本和命令。谢谢你的提示。