代码之家  ›  专栏  ›  技术社区  ›  scope_creep

C PowerShell输出读取器迭代器在管道关闭和释放时得到修改

  •  3
  • scope_creep  · 技术社区  · 16 年前

    我正在从C调用PowerShell脚本。该脚本非常小,是“gps;$host.setshouldexit(9)”,它列出进程,然后发送一个退出代码,由pshost对象捕获。

    我遇到的问题是,当管道停止并被处理时,输出读取器pshost集合似乎仍在写入,并且正在填充。因此,当我尝试将它复制到我自己的输出对象时,当我尝试对它进行迭代时,它会以out-ofmemoryException的形式出现。有时它会,除了与一个集合一起被修改的消息。这是密码。

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

    我在数据周围放置了一个for循环。添加,并且收集中充满了600k+,所以感觉GPS命令仍在运行,但为什么。任何想法。

    事先谢谢。

    1 回复  |  直到 16 年前
        1
  •  0
  •   scope_creep    16 年前

    发现了问题。将结果集合和迭代器命名为相同的名称,因此在迭代时,它将添加到集合中,然后返回迭代器,依此类推。呸!.

    推荐文章