I am calling powershell script from C #. The script is quite small and represents "gps; $ host.SetShouldExit (9)", which lists the process and then sends back the exit code that should be captured by the PSHost object.
The problem is when the pipeline is stopped and removed, the PSHost output collector still seems to be writing and populating. Therefore, when I try to copy it to my own output object, it gets rid of the OutOfMemoryException when I try to iterate over it. Sometimes it will be except when the message has been changed in the collection. Here is the code.
private void ProcessAndExecuteBlock(ScriptBlock Block)
{
Collection<PSObject> PSCollection = new Collection<PSObject>();
Collection<Object> PSErrorCollection = new Collection<Object>();
Boolean Error = false;
int ExitCode=0;
ExecuteScript(Block.Script);
while (PExecutor.PLine.PipelineStateInfo.State == PipelineState.Running)
{
switch (WaitHandle.WaitAny(PExecutor.Hand))
{
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]);
}
}
if (PExecutor.PLine.Output.EndOfPipeline)
{
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();
ExecutionResults ER = new ExecutionResults(Block.RuleGuid,Block.SubRuleGuid, Block.MessageIdentfier);
ER.ExitCode = ExitCode;
lock (ReadSync)
{
if (PSCollection.Count > 0)
{
ER.DataAdd(PSCollection);
}
}
if (Error)
{
if (PSErrorCollection.Count > 0)
{
ER.ErrorAdd(PSErrorCollection);
}
else
{
ER.InError = true;
}
}
EnQueueOutput(ER);
}
and this is the PipelineExecutor class that sets up the pipeline to execute.
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 Data.Add, 600k +, , gps , . .
.