[英]Formatting Output of Hosted PowerShell
我在這里找到了一個C#示例,它從主機應用程序異步調用PowerShell腳本(在文件夾第6章 - 閱讀事件中),並嘗試在Windows窗體應用程序中使用它。
我有一個按鈕(button1)來啟動PowerShell腳本,textBox1是輸入腳本而textBox2是顯示腳本輸出。 這是我目前的代碼:
using System;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Windows.Forms;
namespace PSTestApp
{
delegate void SetTextDelegate(string text);
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
textBox2.Text = "";
Runspace runspace =
RunspaceFactory.CreateRunspace();
runspace.Open();
Pipeline pipeline =
runspace.CreatePipeline(textBox1.Text);
pipeline.Output.DataReady +=
new EventHandler(HandleDataReady);
pipeline.Error.DataReady +=
new EventHandler(HandleDataReady);
pipeline.InvokeAsync();
pipeline.Input.Close();
}
private void HandleDataReady(object sender, EventArgs e)
{
PipelineReader<PSObject> output =
sender as PipelineReader<PSObject>;
if (output != null)
{
while (output.Count > 0)
{
SetText(output.Read().ToString());
}
return;
}
PipelineReader<object> error =
sender as PipelineReader<object>;
if (error != null)
{
while (error.Count > 0)
{
SetText(error.Read().ToString());
}
return;
}
}
private void SetText(string text)
{
if (textBox2.InvokeRequired)
{
SetTextDelegate d = new SetTextDelegate(SetText);
this.Invoke(d, new Object[] { text });
}
else
{
textBox2.Text += (text + Environment.NewLine);
}
}
}
}
代碼有效,但我在處理輸出時遇到問題。 Pipeline.Output.Read()返回PSObject的一個實例,因此ToString()為不同的對象返回不同的東西。 例如,如果我使用此PowerShell命令:
Get-ChildItem
輸出是:
PSTestApp.exe
PSTestApp.pdb
PSTestApp.vshost.exe
PSTestApp.vshost.exe.manifest
如果我使用:
Get-Process
輸出是:
...
System.Diagnostics.Process (csrss)
System.Diagnostics.Process (ctfmon)
System.Diagnostics.Process (devenv)
System.Diagnostics.Process (devenv)
...
我可以使用返回的PSObject實例來構造輸出,但它會很好如果我可以使用現有的PowerShell格式並獲得與控制台中相同的輸出。 當我運行應用程序並檢查Runspace.RunspaceConfiguration.Formats時,計數為9,並且存在DotNetTypes.format.ps1xml,但我不知道如何應用該格式。
我注意到如果我在腳本的末尾添加Out-String:
...
Pipeline pipeline =
runspace.CreatePipeline(textBox1.Text);
pipeline.Commands.Add("Out-String");
...
輸出的格式與標准PowerShell控制台中的格式相同。 這有效,但是如果我運行一個帶有長輸出的腳本需要一些時間來執行:
gci d:\ -recurse
Pipeline.Output.DataReady事件僅引發一次(在執行結束Out-String之后),然后才將輸出添加到文本框中。
有沒有辦法在托管的PowerShell實例中使用標准的PowerShell輸出格式?
如果你在out-string上使用-stream參數,我想你會發現它不會阻塞。
此外,如果您實際構建主機(實現主機接口,包括UI和可能的rawui),您將實現處理“標准”主機輸出的方法。
您也可以嘗試使用out-default而不是out-string。 我知道在自托管環境中我經常使用它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.