中使用PowerShell RunspacePool多线程到远程服务器从C# [英] Using Powershell RunspacePool multithreaded to remote server from C#

查看:427
本文介绍了中使用PowerShell RunspacePool多线程到远程服务器从C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个使用PowerShell的RunspacePool到远程服务器的一些C#code。 所有工作良好时maxRunspaces被设置为1,但将其设置为2给出的麻烦。

I am trying to create some C# code using a Powershell RunspacePool to a remote server. All is working well when maxRunspaces is set to 1, but setting it to 2 gives troubles.

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());
}

在服务器我已经登记注册,PSSessionConfiguration到shellUri指向一个会话配置。该配置采用了startupscript它加载一个管理单元(附加PSSnapinMySnapin)。 至于说用最大的1运行空间时能正常工作。但随着一个最大的2运行空间的第一个任务完成后,接下来给出了一个错误的运行启动脚本抛出错误:使用相同的密钥已经被添加的项目而另一个任务,因为损坏的连接失败。似乎它与装载spanin 2倍的问题。 所以我改变了我的startupscript到

On the server I have registered a session configuration with Register-PSSessionConfiguration to which shellUri is pointing. That configuration uses a startupscript which loads a snapin (Add-PSSnapin 'MySnapin'). As said this works fine when using a max of 1 runspaces. But with a max of 2 runspaces the first task completes, the next gives an error "Running startup script threw an error: An item with the same key has already been added." and the other task fail because of a corrupted connection. Seems it has a problem with loading the spanin 2 times. So I changed my startupscript to

if ((Get-PSSnapin -Name 'MySnapin' -ErrorAction SilentlyContinue) -eq $null)
{
    Add-PSSnapin 'MySnapin'
}

在这种情况下,开池已失败,出现错误: 运行启动脚本抛出错误:否Windows PowerShell管理单元匹配模式MySnapin被发现。检查图案,然后再次尝试该命令。 评论加载PSSnapin线,仍然引发错误,所以它是Get-PSSnapin命令抛出这个错误。因此,它看起来像该ErrorAction SilentlyContinue不repected。

In that case, opening the pool already fails with the error: Running startup script threw an error: No Windows PowerShell snap-ins matching the pattern 'MySnapin' were found. Check the pattern and then try the command again. Commenting the Add-PSSnapin line, still throws the error, so it is the Get-PSSnapin command throwing that error. So it looks like that the ErrorAction SilentlyContinue is not repected.

任何想法?

第二个问题:什么是pool.ApartmentState和pool.ThreadOptions建议的设置?找不到必须的文件。

Second question: what are the recommended settings for pool.ApartmentState and pool.ThreadOptions? Can't find must documentation on that.

更新

我试过的ApartmentState和ThreadOptions的所有组合,但是这并没有什么差别(旁边的STA与UseCurrentThread的组合是不行的,因为服务器进程在MTA模式下运行,这是正常的)。

I tried all the combinations of ApartmentState and ThreadOptions, but that didn't make any difference (beside that the combination of STA with UseCurrentThread does not work, because the server process is running in MTA mode, that's normal).

因此很明显,这是与PSSnapin cmdlet的一个问题。在一个正常的PowerShell进程是没有问题的调用附加PSSnapin多次和ErrorAction SilentlyContinue由Get-PSSnapin cmdlet的尊重。这两件事似乎并不在一个startupscript工作。很奇怪。

So apparently it is a problem with the PSSnapin cmdlets. In a normal Powershell process it is no problem to call Add-PSSnapin multiple times and the ErrorAction SilentlyContinue is respected by the Get-PSSnapin cmdlet. Both things seem not to work in a startupscript. Very strange.

而不是使用添加-PSSnapin,我现在尝试使用导入模块加载程序集和工作正常。

But instead of using Add-PSSnapin, I now tried using Import-Module to load the assembly and that works fine.

我现在不明白的是,改变maxRunspaces参数(1,2或3),似乎并没有把总的持续时间任何区别。但是,这可能是通过这一事实相比,网络流量和延迟在服务器上的操作都比较小而引起的。我应该尝试一个漫长的过程。

What I don't understand now is that varying the maxRunspaces parameter (1, 2 or 3) seems not to make any difference in the total duration. But that's perhaps caused by the fact that the actions on the server are relatively small compared to the network traffic and latency. I should try a long process.

更新2

好了,我现在已经测试了简单的启动睡眠命令,我可以清楚地看到,多线程工作正常。

Ok, I have now tested with a simple Start-Sleep command and I can clearly see that multithreading is working fine.

所以,最终的问题仍然存在处于粗体斜体字以上。虽然我可以通过变通办法,导入模块

So the ultimate problem still existing is in the bold-italic text above. Although I can workaround it by using Import-Module

推荐答案

第一: -ErrorAction SilentlyContinue 只适用于非终止的错误。终止错误抛出,不写的,必须抓住,不燮pressed。 请不要让我开始。

First: -ErrorAction SilentlyContinue only applies to "non-terminating" errors. Terminating errors are thrown, not written, and must be caught, not suppressed. Please don't get me started.

在换句话说,使用ErrorAction标志包装在尝试{...}赶上{...} 块来代替。

In other words, wrap it in a try { ... } catch { ... } block instead of using the ErrorAction flag.

二:为什么你想加载它作为一个管理单元呢? Snapins是的实际上的德precated。在MSDN文档特写法是要知道的Windows PowerShell 2.0引入了模块的支持,这是preferred方法添加cmdlet和提供。

Second: Why are you trying to load it as a snapin anyway? Snapins are essentially deprecated. Te wording on the MSDN docs is "Be aware that Windows PowerShell 2.0 introduced support for modules, which is the preferred method to add cmdlets and providers."

他们是死的功能,它不会被扩大,由模块在这一点上是完全替换。你说,它的工作原理与导入模块。这就是你的答案。导入模块。不要用老办法。

They're a dead feature which won't be expanded and is fully replaced by modules at this point. You say that it works with Import-Module. That's your answer. Import-Module. Don't use the old way.

这篇关于中使用PowerShell RunspacePool多线程到远程服务器从C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆