使用实时输出从C#调用脚本块

使用实时输出从C#调用脚本块,c#,powershell,C#,Powershell,我想在PowerShell模块中编写一个类类型定义。这个列表包含一个包含脚本块和一些其他变量的列表。它还有一个函数来调用其可用列表中的所有脚本块 为了调用脚本块,我尝试了几种方法,并以最简单的方法结束,例如: Powershell psinstance = PowerShell.Create() psinstance.AddScript("bla bla bla") psinstance.Invoke() 到目前为止,这很好,但我有一个微妙的细节,我想有 此调用仅在输出完全完成后返回输出 对于

我想在PowerShell模块中编写一个类类型定义。这个列表包含一个包含脚本块和一些其他变量的列表。它还有一个函数来调用其可用列表中的所有脚本块

为了调用脚本块,我尝试了几种方法,并以最简单的方法结束,例如:

Powershell psinstance = PowerShell.Create()
psinstance.AddScript("bla bla bla")
psinstance.Invoke()
到目前为止,这很好,但我有一个微妙的细节,我想有

此调用仅在输出完全完成后返回输出

对于一个特定的例子,让我们使用另一个scriptblock,它最好地描述了这个问题。首先直接从PowerShell:

$a = { ping 127.0.0.1 }
如果你用这个

& $a

您将直接获得逐行输出。因此,第一次ping发送时,您将收到第一行,第二次ping发送时,您将收到第二行,依此类推

但是如果你做了一个

$a.Invoke()
只有在发送了4次ping之后,即4秒之后,您才能获得完整的结果。或者,如果您使用t参数,它将永远运行,而没有任何输出

如果我通过C#代码调用这个脚本块,我也会遇到同样的“问题”

但我希望在PowerShell内部使用call操作符或
Invoke表达式时得到的行为

我如何接收控制台的实时输出?

如果我知道&operator(或
Invoke Expression
)在.Net背景中到底在做什么,我也会很高兴


但也许这只是我看不到的东西。有人知道吗?

invoke命令允许为输出添加一个参数(IList)。如果使用observablecollection作为输出参数并附加到CollectionChanged事件,则可以将输出写入控制台:

var psinstance = System.Management.Automation.PowerShell.Create();
psinstance.AddScript("ping 127.0.0.1");

var output = new System.Collections.ObjectModel.ObservableCollection<string>();
output.CollectionChanged += (object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) =>
{
    foreach(var item in e.NewItems)
        Console.WriteLine(item);
};
psinstance.Invoke(null, output);
var psinstance=System.Management.Automation.PowerShell.Create();
psinstance.AddScript(“ping 127.0.0.1”);
var output=new System.Collections.ObjectModel.ObservableCollection();
output.CollectionChanged+=(对象发送方,System.Collections.Specialized.NotifyCollectionChangedEventArgs e)=>
{
foreach(e.NewItems中的var项)
控制台写入线(项目);
};
psinstance.Invoke(null,输出);

调用命令允许为输出添加参数(IList)。如果使用observablecollection作为输出参数并附加到CollectionChanged事件,则可以将输出写入控制台:

var psinstance = System.Management.Automation.PowerShell.Create();
psinstance.AddScript("ping 127.0.0.1");

var output = new System.Collections.ObjectModel.ObservableCollection<string>();
output.CollectionChanged += (object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) =>
{
    foreach(var item in e.NewItems)
        Console.WriteLine(item);
};
psinstance.Invoke(null, output);
var psinstance=System.Management.Automation.PowerShell.Create();
psinstance.AddScript(“ping 127.0.0.1”);
var output=new System.Collections.ObjectModel.ObservableCollection();
output.CollectionChanged+=(对象发送方,System.Collections.Specialized.NotifyCollectionChangedEventArgs e)=>
{
foreach(e.NewItems中的var项)
控制台写入线(项目);
};
psinstance.Invoke(null,输出);

我认为此选项也可能符合您的标准:

start-job -ScriptBlock { ping 127.0.0.1 } | Receive-Job -Wait

我认为该选项也可能符合您的标准:

start-job -ScriptBlock { ping 127.0.0.1 } | Receive-Job -Wait

我在一个演示项目中尝试了这个方法,效果非常好。我将把它包括在我的主项目中,在那里我将删除Process类的使用。到目前为止,我认为这个应该被标记为这个问题的答案。我在一个演示项目中尝试了这个方法,效果非常好。我将把它包括在我的主项目中,在那里我将删除Process类的使用。到目前为止,我认为这一条应该被标记为问题的答案