Я нашел пример C# here для асинхронного вызова сценария PowerShell из главного приложения (в папке Глава 6 - Чтение с помощью событий) и пытаюсь использовать его в приложении Windows Forms.Форматирование вывода Hosted PowerShell
У меня есть кнопка (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 для const ruct выход, но было бы неплохо. Если бы я мог использовать существующее форматирование 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?
Отлично, спасибо за ответ. –