Как я могу адаптировать пользовательский хост Powershell к пользовательскому интерфейсу WPF, поддерживая ввод-вывод из программ, запущенных на хосте? - PullRequest
2 голосов
/ 02 ноября 2011

Я пытаюсь адаптировать пример Host03, найденный здесь (http://msdn.microsoft.com/en-us/library/windows/desktop/ee706577(v=vs.85).aspx), для использования интерфейса WPF. Я попытался завершить это, создав пользовательские StringWriter и StringReader и установив Console.Out и Console.In для моего пользовательские классы. Вот как выглядит код прототипа:

namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    private ConsoleWriter _consoleWriter;
    private TextWriter _textWriter;
    private ConsoleReader _consoleReader;
    private TextReader _textReader;

    public MainWindow()
    {
        InitializeComponent();
        _textWriter = Console.Out;
        _textReader = Console.In;
        _consoleWriter = new ConsoleWriter(ref tb);
        Console.SetOut(_consoleWriter);
        tb.KeyUp += OnTextInputKeyUp;
    }

    private void OnTextInputKeyUp(object sender, KeyEventArgs e)
    {
        if(e.Key == Key.Enter)
        {
            _consoleReader = new ConsoleReader(tb.Text);
            Console.SetIn(_consoleReader);
            var input = Console.ReadLine();
// I'm creating a thread here, because otherwise the following exception occurs:
// "The calling thread cannot access this object because a different thread owns it"
            var t = new Thread(new ThreadStart(
                delegate
                    {
// PSListenerConsoleSample is the class used in the Host03 sample which I am trying to adapt
// The execute method in PShellListener has been made public for prototype purposes,
// in the sample it is private
                        var listener = new PSListenerConsoleSample();
                        listener.Execute(input);
                    }));
            t.Start();
        }
    }

    ~MainWindow()
    {
        Console.SetOut(_textWriter);    // Redirect Console back to original TextWriter. 
        Console.SetIn(_textReader);
        _consoleWriter.Close();         // Close our ConsoleWriter TextWriter. 
    }
}

public class ConsoleWriter : StringWriter
{
    private TextBox _textBox;

    public ConsoleWriter(ref TextBox textBox)
    {
        _textBox = textBox;
    }

    public override void WriteLine(string value)
    {
        if (_textBox.Dispatcher.CheckAccess())
        {
            _textBox.Text += value + "\n";
        }
        else
        {
            _textBox.Dispatcher.Invoke(DispatcherPriority.Normal,
                                       (Action)(() => { _textBox.Text += "\n" + value + "\n"; }));
        }
    }
}
public class ConsoleReader : StringReader
{
    private string _s;

    public ConsoleReader(string s) : base(s)
    {
        _s = s;
    } 

    public override string ReadLine()
    {
        return _s;
    }
}
}

В настоящее время класс ConsoleReader возвращает весь отображаемый текст, поэтому он предназначен для работы только с первой введенной командой. Например, если я ввожу «ls» и нажимаю ввод, отображается содержимое моего каталога bin \ debug. Проблема в том, что я пытаюсь поддерживать программы, требующие ввода-вывода. Например, рассмотрим следующее консольное приложение:

namespace DemoQuestion
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, I am the program you just called. Please enter something:");
            var input = Console.ReadLine();
            Console.WriteLine("I received the following input from you: {0}", input);
        }
    }
}

Эта простая программа прекрасно работает в образце Host03, запрашивая у пользователя ввод, а затем считывая и отображая его. В моем адаптированном примере, если я ввожу «T: \ DemoQuestion.exe», происходит первоначальный Console.WriteLine, отображающий «Привет, я и т. Д.», Но я не могу понять, как вернуть ввод пользователя в программу.

Я прошу прощения за сложность вопроса, я старался изо всех сил, чтобы упростить его. Пожалуйста, дайте мне знать, если у вас есть какие-либо вопросы.

1 Ответ

0 голосов
/ 13 марта 2014

Просто предложение. Может быть нетривиально написать консольный GUI с нуля, который может обрабатывать как ввод, так и вывод, может быть, поэтому в PowerShell ISE не было такого до PowerShell 3.0. Поэтому, возможно, вам следует попытаться сделать то, что было сделано в PowerShell ISE до версии 3.0. Имеют два отдельных элемента пользовательского интерфейса, один для ввода, другой для вывода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...