使用实时输出从C#调用ScriptBlocks

时间:2016-10-20 14:12:05

标签: c# powershell

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

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

Powershell psinstance = PowerShell.Create()
psinstance.AddScript("bla bla bla")
psinstance.Invoke()

到目前为止这种方法很好,但我有一个我想要的细节。

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

对于一个具体的例子,让我们使用另一个脚本块,它最好地描述了这个问题。首先来自PowerShell:

$a = { ping 127.0.0.1 }

如果你用

运行这个
& $a

Invoke-Expression $a

您将直接获得逐行输出。所以第一个ping发送你将收到第一行,第二个ping发送,你将收到第二行,依此类推。

但如果你做了

$a.Invoke()

只有在4秒后发送完毕后才能获得完整的结果。或者如果你使用t参数,它将永远运行而没有输出。

如果我通过C#代码

调用此脚本块,则会得到相同的“问题”

但是我想要在PowerShell中使用调用运算符或Invoke-Expression时会得到的行为。

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

如果我知道&运算符(或Invoke-Expression)正在.Net背景中完成。

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

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:-1)

我认为此选项也可能符合您的条件:

start-job -ScriptBlock { ping 127.0.0.1 } | Receive-Job -Wait
相关问题