我试图使用 Powershell RunspacePool 到远程服务器创建一些 C# 代码。 当 maxRunspaces 设置为 1 时,所有工作都正常进行,但将其设置为 2 会出现问题。
var connectionInfo = new WSManConnectionInfo(target, shellUri, credential);
using (RunspacePool pool = RunspaceFactory.CreateRunspacePool(1, 2,
connectionInfo))
{
pool.ApartmentState = System.Threading.ApartmentState.STA;
pool.ThreadOptions = PSThreadOptions.UseNewThread;
pool.Open();
var tasks = new List<Task>();
for (var i = 0; i < 12; i++)
{
var taskID = i;
var ps = PowerShell.Create();
ps.RunspacePool = pool;
ps.AddCommand("Get-NAVServerInstance");
var task = Task<PSDataCollection<PSObject>>.Factory.FromAsync(
ps.BeginInvoke(), r => ps.EndInvoke(r));
System.Diagnostics.Debug.WriteLine(
string.Format("Task {0} created", task.Id));
task.ContinueWith(t => System.Diagnostics.Debug.WriteLine(
string.Format("Task {0} completed", t.Id)),
TaskContinuationOptions.OnlyOnRanToCompletion);
task.ContinueWith(t => System.Diagnostics.Debug.WriteLine(
string.Format("Task {0} faulted ({1} {2})", t.Id,
t.Exception.InnerExceptions.Count,
t.Exception.InnerException.Message)),
TaskContinuationOptions.OnlyOnFaulted);
tasks.Add(task);
}
Task.WaitAll(tasks.ToArray());
}
在服务器上,我已经使用Register-PSSessionConfiguration注册了一个会话配置,其中shellUri指向该配置。该配置使用一个启动脚本来加载一个snapin(Add-PSSnapin 'MySnapin')。 正如所说的,当使用最多1个runspace时,这个工作正常。但是,如果最大运行空间为2,则第一个任务完成,下一个任务会出现错误“运行启动脚本引发错误:已添加具有相同键的项。”并且其他任务失败,因为连接已损坏。似乎它在两次加载spanin时存在问题。 因此,我将我的启动脚本更改为
if ((Get-PSSnapin -Name 'MySnapin' -ErrorAction SilentlyContinue) -eq $null)
{
Add-PSSnapin 'MySnapin'
}
在这种情况下,打开池时已经出现错误: 运行启动脚本引发了一个错误:找不到与模式“MySnapin”匹配的Windows PowerShell快照。检查模式,然后再次尝试该命令。 即使注释掉 Add-PSSnapin 行,仍会抛出错误,因此是 Get-PSSnapin 命令引发该错误。所以看起来 ErrorAction SilentlyContinue 没有得到遵守。
有什么想法吗?
第二个问题:pool.ApartmentState 和 pool.ThreadOptions 的推荐设置是什么?找不到相关文档。
更新:
我尝试了所有的 ApartmentState 和 ThreadOptions 组合,但没有任何区别(除了 STA 与 UseCurrentThread 组合无法工作,因为服务器进程在 MTA 模式下运行,这很正常)。
因此显然是 PSSnapin cmdlet 的问题。在普通的 Powershell 进程中,调用 Add-PSSnapin 多次没有问题,Get-PSSnapin cmdlet 也可以遵守 ErrorAction SilentlyContinue。这两件事在启动脚本中似乎都不起作用。非常奇怪。
但是,我现在尝试使用 Import-Module 加载程序集,这个方法很好用。
现在我不明白的是,变化 maxRunspaces 参数(1、2 或 3)似乎不会对总持续时间产生任何影响。但这可能是由于服务器上的操作相对于网络流量和延迟而言相对较小。我应该尝试一个长进程。
更新 2:
好的,现在我使用了一个简单的 Start-Sleep 命令进行了测试,我可以清楚地看到多线程正常工作。
因此,最终存在的问题仍然是上面加粗和倾斜的文字。虽然我可以通过使用 Import-Module 来解决它。