简体   繁体   English

执行每个管道命令后,在C#中捕获PowerShell输出

[英]Capturing PowerShell output in C# after execution of each pipeline command

I am implementing a WPF application that executes a PowerShell script for each key/value pair given in a dictionary, using the pair as script arguments. 我正在实现一个WPF应用程序,该应用程序为字典中给出的每个键/值对执行PowerShell脚本,使用该对作为脚本参数。 I store each run of the script as a new command in the pipeline. 我将脚本的每次运行存储为管道中的新命令。 However, this causes me to only get output back from the last command that was run, when I need the output after each run of the script. 但是,这导致我只能从运行的最后一个命令返回输出,当我在每次运行脚本后需要输出时。 I have considered creating a new pipeline each time the script is executed, but I need to know when all executions of the script are done. 我每次执行脚本时都考虑过创建一个新的管道,但我需要知道脚本的所有执行何时完成。 Here's the relevant code to help explain my problem: 这是帮助解释我的问题的相关代码:

private void executePowerShellScript(String scriptText, Dictionary<String, String> args)
{
     // Create the PowerShell object.
     PowerShell powerShell = PowerShell.Create();

     // If arguments were given, add the script and its arguments.
     if (args != null)
     {
          foreach (KeyValuePair<String, String> arg in args)
          {
               powerShell.AddScript(scriptText);
               powerShell.AddArgument(arg.Key);
               powerShell.AddArgument(arg.Value);
          }
     }

     // Otherwise, just add the script.
     else
          powerShell.AddScript(scriptText);

     // Add the event handlers.
     PSDataCollection<PSObject> output = new PSDataCollection<PSObject>();
     output.DataAdded += new EventHandler<DataAddedEventArgs>(Output_DataAdded);
     powerShell.InvocationStateChanged +=
          new EventHandler<PSInvocationStateChangedEventArgs>(Powershell_InvocationStateChanged);

     // Invoke the pipeline asynchronously.
     IAsyncResult asyncResult = powerShell.BeginInvoke<PSObject, PSObject>(null, output);
}

private void Output_DataAdded(object sender, DataAddedEventArgs e)
{
     PSDataCollection<PSObject> myp = (PSDataCollection<PSObject>)sender;

     Collection<PSObject> results = myp.ReadAll();
     foreach (PSObject result in results)
     {
          Console.WriteLine(result.ToString());
     }
}

And then I use the following method to know when all executions of the script have been completed. 然后我使用以下方法来了解脚本的所有执行何时完成。 Since I do this by checking that the invocation state of the pipeline is completed, I can't make a new pipeline for each execution of the script: 由于我通过检查管道的调用状态是否已完成来执行此操作,因此无法为每次执行脚本创建新管道:

private void Powershell_InvocationStateChanged(object sender, PSInvocationStateChangedEventArgs e)
{
     switch (e.InvocationStateInfo.State)
     {
          case PSInvocationState.Completed:
               ActiveCommand.OnCommandSucceeded(new EventArgs());
               break;
          case PSInvocationState.Failed:
               OnErrorOccurred(new ErrorEventArgs((sender as PowerShell).Streams.Error.ReadAll()));
               break;
     }
     Console.WriteLine("PowerShell object state changed: state: {0}\n", e.InvocationStateInfo.State);
}

So, to get to my question: 那么,来回答我的问题:

1) Can I force the pipeline to produce output after each command that it executes? 1)在执行每个命令后,我可以强制管道产生输出吗? Or, 要么,
2) If I were to create a new pipeline each time I run the command, is there another way that I could check that all executions of the script have been completed? 2)如果我每次运行命令时都要创建一个新管道,还有另一种方法可以检查脚本的所有执行是否都已完成?

There are few examples using the actual PowerShell class in C# and I know next to nothing about threading, so any help would be greatly appreciated. 在C#中使用实际的PowerShell类的例子很少,我对线程几乎一无所知,所以任何帮助都会非常感激。

I feel silly for answering my own question, but all I did was move the loop functionality from my C# code into my script and that worked. 我对回答我自己的问题感到愚蠢,但我所做的就是将循环功能从我的C#代码转移到我的脚本中并且有效。 So now I pass all the keys and values at once as array parameters and only have the one command in the pipeline. 所以现在我将所有键和值一次作为数组参数传递,并且只在管道中有一个命令。

I would still be interested to know if it is possible to produce output after each command in the pipeline is executed, though. 不过,我仍然有兴趣知道是否可以在执行管道中的每个命令后生成输出。

I have a situation where I have an object that manages a PowerShell environment, and it takes a script or a module and cmdlet and executes it and then takes a new script or module and cmdlet or cmdlet from the original module and executes it. 我有一种情况,我有一个管理PowerShell环境的对象,它需要一个脚本或模块和cmdlet并执行它,然后从原始模块获取一个新的脚本或模块和cmdlet或cmdlet并执行它。 Each time something is executed, I need to return the results. 每次执行某些操作时,我都需要返回结果。 I solved it by clearing the command queue after each execution: 我通过在每次执行后清除命令队列来解决它:

powerShellInstance.Commands.Clear();

hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM