4

リモート サーバーへの 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());
}

サーバー上で、shellUri が指している Register-PSSessionConfiguration を使用してセッション構成を登録しました。この構成では、スナップインを読み込むスタートアップ スクリプト (Add-PSSnapin 'MySnapin') を使用します。前述のように、最大​​ 1 つの実行空間を使用する場合、これは正常に機能します。ただし、最大 2 つの実行空間で最初のタスクが完了すると、次のタスクで「スタートアップ スクリプトの実行中にエラーが発生しました: 同じキーを持つ項目が既に追加されています」というエラーが表示されます。接続が破損しているため、他のタスクは失敗します。スパニンを2回ロードすることに問題があるようです。そこで、スタートアップスクリプトを次のように変更しました

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

その場合、プールを開くことは既に次のエラーで失敗しています: スタートアップ スクリプトの実行中にエラーが発生しました: パターン 'MySnapin' に一致する Windows PowerShell スナップインが見つかりませんでした。パターンを確認してから、コマンドを再試行してください。Add-PSSnapin 行にコメントを付けてもエラーがスローされるため、そのエラーをスローするのは Get-PSSnapin コマンドです。そのため、ErrorAction SilentlyContinue が反映されていないようです。

何か案は?

2 番目の質問: pool.ApartmentState と pool.ThreadOptions の推奨設定は何ですか? それに関する必要なドキュメントが見つかりません。

更新

ApartmentState と ThreadOptions のすべての組み合わせを試しましたが、違いはありませんでした (サーバー プロセスが MTA モードで実行されているため、STA と UseCurrentThread の組み合わせは機能しません)。

どうやら PSSnapin コマンドレットに問題があるようです。通常の Powershell プロセスでは、Add-PSSnapin を複数回呼び出しても問題はなく、ErrorAction SilentlyContinue は Get-PSSnapin コマンドレットによって尊重されます。どちらもスタートアップスクリプトでは機能しないようです。非常に奇妙な。

しかし、Add-PSSnapin を使用する代わりに、Import-Module を使用してアセンブリをロードしようとしたところ、問題なく動作しました。

私が今理解していないのは、maxRunspaces パラメーター (1、2、または 3) を変更しても、合計期間に違いがないように見えるということです。しかし、これはおそらく、ネットワーク トラフィックと待ち時間に比べて、サーバーでのアクションが比較的小さいという事実が原因です。長いプロセスを試さなければなりません。

更新 2 :

OK、簡単な Start-Sleep コマンドでテストしたところ、マルチスレッドが正常に動作していることがはっきりとわかりました。

したがって、依然として存在する究極の問題は、上記の太字イタリック体のテキストにあります。Import-Module を使用して回避できますが、

4

1 に答える 1

0

最初: -ErrorAction SilentlyContinue「非終了」エラーにのみ適用されます。終了エラーはスローされ、書き込まれず、抑制されずにキャッチされる必要があります。私を始めさせないでください。

つまり、try { ... } catch { ... }ErrorAction フラグを使用する代わりに、ブロックでラップします。

2番目: とにかくスナップインとしてロードしようとしているのはなぜですか? Snapins は基本的に非推奨です。MSDN ドキュメントの文言は、「Windows PowerShell 2.0 でモジュールのサポートが導入されたことに注意してください。これは、コマンドレットとプロバイダーを追加するための推奨される方法です。」

それらは拡張されず、この時点でモジュールに完全に置き換えられる機能はありません。Import-Module で動作するとおっしゃっています。それがあなたの答えです。インポート モジュール。古い方法を使用しないでください。

于 2014-04-16T21:52:38.597 に答える