c#-4.0 - C# powershell 输出读取器迭代器在管道关闭和处置时被修改

标签 c#-4.0 powershell-2.0

我正在从 C# 调用 powershell 脚本。该脚本非常小,是“gps;$host.SetShouldExit(9)”,它列出了进程,然后发回一个退出代码以供 PSHost 对象捕获。

我遇到的问题是,当管道停止并处理后,输出读取器 PSHost 集合似乎仍在写入,并且正在填满。因此,当我尝试将其复制到我自己的输出对象时,当我尝试对其进行迭代时,它会出现 OutOfMemoryException。有时它会带有 Collection was modified 消息。这是代码。

 private void ProcessAndExecuteBlock(ScriptBlock Block)
   {
       Collection<PSObject> PSCollection = new Collection<PSObject>();
       Collection<Object> PSErrorCollection = new Collection<Object>();
       Boolean Error = false;
       int ExitCode=0;

       //Send for exection. 
       ExecuteScript(Block.Script);

       // Process the waithandles. 
       while (PExecutor.PLine.PipelineStateInfo.State  == PipelineState.Running)
       {
           // Wait for either error or data waithandle. 
           switch (WaitHandle.WaitAny(PExecutor.Hand))
           {
               // Data
               case 0:
                   Collection<PSObject> data =   PExecutor.PLine.Output.NonBlockingRead();
                   if (data.Count  > 0)
                   {
                       for (int cnt = 0; cnt <= (data.Count-1); cnt++)
                       {
                           PSCollection.Add(data[cnt]); 
                       }
                   }

                   // Check to see if the pipeline has been closed. 
                   if (PExecutor.PLine.Output.EndOfPipeline)
                   { 
                       // Bring back the exit code. 
                       ExitCode = RHost.ExitCode; 
                   }
                   break;
               case 1:
                   Collection<object> Errordata = PExecutor.PLine.Error.NonBlockingRead();
                   if (Errordata.Count > 0)
                   {
                       Error = true;
                       for (int count = 0; count <= (Errordata.Count - 1); count++)
                       {
                           PSErrorCollection.Add(Errordata[count]);
                       }
                   }
                   break;
           }
       }

       PExecutor.Stop();

       // Create the Execution Return block
       ExecutionResults ER = new ExecutionResults(Block.RuleGuid,Block.SubRuleGuid, Block.MessageIdentfier);
       ER.ExitCode = ExitCode;

       // Add in the data results.
       lock (ReadSync)
       {
           if (PSCollection.Count > 0)
           {
               ER.DataAdd(PSCollection);
           }
       }

       // Add in the error data if any.
       if (Error)
       {
           if (PSErrorCollection.Count > 0)
           {
               ER.ErrorAdd(PSErrorCollection);
           }
           else
           {
               ER.InError = true;
           }
       }

       // We have finished, so enque the block back. 
       EnQueueOutput(ER);
   }

这是 PipelineExecutor 类,它设置执行管道。

public class PipelineExecutor
{
    private Pipeline pipeline;
    private WaitHandle[] Handles;

    public Pipeline PLine
    {
        get { return pipeline; }
    }

    public WaitHandle[] Hand 
    {
        get { return Handles; }
    }

    public PipelineExecutor(Runspace runSpace, string command)
    {       
        pipeline = runSpace.CreatePipeline(command);
        Handles = new WaitHandle[2];
        Handles[0] = pipeline.Output.WaitHandle;
        Handles[1] = pipeline.Error.WaitHandle;
    }

    public void Start()
    {
        if (pipeline.PipelineStateInfo.State == PipelineState.NotStarted)
        {
            pipeline.Input.Close();
            pipeline.InvokeAsync();
        }
    }

    public void Stop()
    {
        pipeline.StopAsync();
    }
}

这是发生异常的 DataAdd 方法。

    public void DataAdd(Collection<PSObject> Data)
    {
        foreach (PSObject Ps in Data)
        {
            Data.Add(Ps);
        }
    }

我在 Data.Add 周围放置了一个 for 循环,并且集合充满了 600k+ 所以感觉 gps 命令仍在运行,但为什么。任何想法。

提前致谢。

最佳答案

发现问题。将生成的集合和迭代器命名为相同的名称,以便在迭代时将其添加到集合中,然后返回到迭代器中,依此类推。啊!

关于c#-4.0 - C# powershell 输出读取器迭代器在管道关闭和处置时被修改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2841922/

相关文章:

powershell - 在Powershell中一次移动或复制多个文件

wpf - 如何访问 DataGridTemplateColumn 中的控件以获取值?

c# - 在 Entity Framework 6.1 中添加存储过程的问题

.net - 为什么.NET 试图加载一个不存在的程序集?

powershell - 如何在非提升的 powershell 中运行 w32tm

xml - 使用Powershell编写xml

C#比较两个集合的更有效方法

c# - 将选定值的集合从 Select2-Multi DropDownList 传递到 Controller

PowerShell:创建本地用户帐户

powershell - 删除所有 .ica 文件