C# 从C使用Powershell RunspacePool多线程到远程服务器#

C# 从C使用Powershell RunspacePool多线程到远程服务器#,c#,.net,powershell,powershell-remoting,C#,.net,Powershell,Powershell Remoting,我正在尝试使用Powershell RunspacePool创建一些C代码到远程服务器。 当maxRunspaces设置为1时,一切都正常,但将其设置为2会带来麻烦 var connectionInfo = new WSManConnectionInfo(target, shellUri, credential); using (RunspacePool pool = RunspaceFactory.CreateRunspacePool(1, 2,

我正在尝试使用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());
}
在这种情况下,打开池已经失败,出现以下错误: 运行启动脚本时引发错误:未找到与模式“MySnapin”匹配的Windows PowerShell管理单元。请检查模式,然后重试该命令。 注释addpssnapin行仍会抛出错误,因此是Get-PSSnapin命令抛出该错误。所以看起来ErrorAction SilentlyContinue没有重复

有什么想法吗

第二个问题:pool.ApartmentState和pool.ThreadOptions的建议设置是什么?找不到关于这个的文档

更新

我尝试了ApartmentState和ThreadOptions的所有组合,但没有任何区别(除此之外,STA与UseCurrentThread的组合不起作用,因为服务器进程在MTA模式下运行,这是正常的)

显然,PSSnapin cmdlet存在问题。在正常的Powershell进程中,多次调用Add-PSSnapin是没有问题的,Get-PSSnapin cmdlet遵守ErrorAction SilentlyContinue。这两件事在startupscript中似乎都不起作用。非常奇怪。

但是我现在没有使用AddPSSNapin,而是尝试使用Import模块加载程序集,效果很好

我现在不明白的是,改变maxRunspaces参数(1、2或3)似乎不会对总持续时间产生任何影响。但这可能是由于服务器上的操作与网络流量和延迟相比相对较小。我应该尝试一个漫长的过程

更新2

好的,我现在已经用一个简单的Start-Sleep命令进行了测试,我可以清楚地看到多线程工作正常


因此,最终的问题仍然存在于上面的粗体斜体文本中。尽管我可以首先使用导入模块解决此问题:
-ErrorAction SilentlyContinue
仅适用于“非终止”错误。终止错误被抛出,而不是写入,并且必须捕获,而不是抑制。请不要让我开始

换句话说,将其包装在
try{…}catch{…}
块中,而不是使用ErrorAction标志

第二:你为什么要把它作为管理单元加载?管理单元基本上已弃用。MSDN文档中的Te措辞是“请注意,Windows PowerShell 2.0引入了对模块的支持,这是添加cmdlet和提供程序的首选方法。”


它们是一个死特性,不会被扩展,现在完全被模块所取代。您说它与导入模块一起工作。这就是你的答案。导入模块。不要使用旧方法。

在远程计算机上注册PSSessionConfiguration时,是否使用了
-UseSharedProcess
参数?如果是这样,请尝试在不使用该参数的情况下注册。FYI@Keith:否,我没有使用-UseSharedProcess参数Add管理单元仅适用于Powershell V1兼容性。它要求管理单元是一个已注册的DLL,具有注册表设置。导入模块是V2及更高版本中的首选方法。模块可以是任何有效的powershell代码,无需注册。
if ((Get-PSSnapin -Name 'MySnapin' -ErrorAction SilentlyContinue) -eq $null)
{
    Add-PSSnapin 'MySnapin'
}