c# выполняют CL exe или обрабатывают в пакетном режиме вывод cpture, ЖИВОЙ к текстовому полю?

Действительно ли возможно запустить какую-либо основанную на командной строке программу или пакетный файл и capturer (перенаправление) помещенный в текстовое поле LIVE

CL занимает время, и он производит текст!

что-то как tracert.exe (это занимает время и производит хорошую сумму текста).

на самом деле я буду работать с tracert.exe, и мне нравится получать живой вывод и показывать его в текстовом поле, в то время как это работает

Править: Моя проблема состоит в том, чтобы иметь его ЖИВОЙ, я имею в виду любую новую строку или обугливаюсь, консольный продукт будет отправлен/вытянут в текстовое поле, Только когда программа сделана!

Просто я хочу создать, точно похож на этот http://www.codeproject.com/KB/threads/redir.aspx (проверьте демонстрацию), но в C#

вот мой код:

private void button1_Click(object sender, EventArgs e)
{    
     Process pc = new Process();
     pc.StartInfo.FileName = "tracert.exe";
     pc.StartInfo.Arguments = "google.com";
     pc.StartInfo.UseShellExecute = false;
     pc.StartInfo.RedirectStandardOutput = true;
     pc.StartInfo.CreateNoWindow = true;
     pc.Start();

     richTextBox1.Text = pc.StandardOutput.ReadToEnd();

     pc.WaitForExit();    
}

Править

с Вашей справкой (большое спасибо парни) и эта ссылка: http://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=EN-US&k=k%28EHINVALIDOPERATION.WINFORMS.ILLEGALCROSSTHREADCALL%29;k%28TargetFrameworkMoniker-%22.NETFRAMEWORK%2cVERSION%3dV2.0%22%29;k%28DevLang-CSHARP%29&rd=true

Я решаю его с этим кодом (Вы думаете, что это в порядке?):

namespace GUIforCL2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        Process _cmd;

        delegate void SetTextCallback(string text);

        private void SetText(string text)
        {
            if (this.richTextBox1.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.richTextBox1.Text += text + Environment.NewLine;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            ProcessStartInfo cmdStartInfo = new ProcessStartInfo("tracert.exe");
            cmdStartInfo.Arguments = "google.com";
            cmdStartInfo.CreateNoWindow = true;
            cmdStartInfo.RedirectStandardInput = true;
            cmdStartInfo.RedirectStandardOutput = true;
            cmdStartInfo.RedirectStandardError = true;
            cmdStartInfo.UseShellExecute = false;
            cmdStartInfo.WindowStyle = ProcessWindowStyle.Hidden;

            _cmd = new Process();
            _cmd.StartInfo = cmdStartInfo;

            if (_cmd.Start())
            {
                _cmd.OutputDataReceived += new DataReceivedEventHandler(_cmd_OutputDataReceived);
                _cmd.ErrorDataReceived += new DataReceivedEventHandler(_cmd_ErrorDataReceived);
                _cmd.Exited += new EventHandler(_cmd_Exited);

                _cmd.BeginOutputReadLine();
                _cmd.BeginErrorReadLine();
            }
            else
            {
                _cmd = null;
            }
        }

        void _cmd_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            UpdateConsole(e.Data);
        }

        void _cmd_ErrorDataReceived(object sender, DataReceivedEventArgs e)
        {
            UpdateConsole(e.Data, Brushes.Red);
        }

        void _cmd_Exited(object sender, EventArgs e)
        {
            _cmd.OutputDataReceived -= new DataReceivedEventHandler(_cmd_OutputDataReceived);
            _cmd.Exited -= new EventHandler(_cmd_Exited);
        }

        private void UpdateConsole(string text)
        {
            UpdateConsole(text, null);
        }
        private void UpdateConsole(string text, Brush color)
        {
            WriteLine(text, color);
        }

        private void WriteLine(string text, Brush color)
        {
            if (text != null)
            {    
                SetText(text);
            }
        }
    }
}

5
задан Amicable 30 April 2014 в 15:12
поделиться

2 ответа

Когда вы создаете экземпляр Process для tracert, вам необходимо установить ProcessStartInfo.UseShellExecute на ] false и ProcessStartInfo.RedirectStandardOutput на true . Это позволит вам использовать свойство Process.StandardOutput для чтения вывода.

Вы можете использовать Process.BeginOutputReadLine , чтобы начать асинхронное чтение и добавить обработчик событий в Process.OutputDataReceived .

Обновление: Вот пример программы WPF, которая делает то, что вы хотите.

MainWindow.xaml:

<Window x:Class="Console.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded" Closed="Window_Closed">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <ScrollViewer Name="outputViewer" SizeChanged="ScrollViewer_SizeChanged" >
            <TextBlock Name="output" />
        </ScrollViewer>
        <TextBox Grid.Row="1" Name="input" KeyDown="input_KeyDown" />
    </Grid>
</Window>

MainWindow.cs:

using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;

namespace Console
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            ProcessStartInfo cmdStartInfo = new ProcessStartInfo("cmd.exe");
            cmdStartInfo.CreateNoWindow = true;
            cmdStartInfo.RedirectStandardInput = true;
            cmdStartInfo.RedirectStandardOutput = true;
            cmdStartInfo.RedirectStandardError = true;
            cmdStartInfo.UseShellExecute = false;
            cmdStartInfo.WindowStyle = ProcessWindowStyle.Hidden;

            _cmd = new Process();
            _cmd.StartInfo = cmdStartInfo;

            if (_cmd.Start() == true)
            {
                _cmd.OutputDataReceived += new DataReceivedEventHandler(_cmd_OutputDataReceived);
                _cmd.ErrorDataReceived += new DataReceivedEventHandler(_cmd_ErrorDataReceived);
                _cmd.Exited += new EventHandler(_cmd_Exited);

                _cmd.BeginOutputReadLine();
                _cmd.BeginErrorReadLine();
            }
            else
            {
                _cmd = null;
            }
        }

        private void Window_Closed(object sender, EventArgs e)
        {
            if ((_cmd != null) &&
                (_cmd.HasExited != true))
            {
                _cmd.CancelErrorRead();
                _cmd.CancelOutputRead();
                _cmd.Close();
                _cmd.WaitForExit();
            }
        }

        void _cmd_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            UpdateConsole(e.Data);
        }

        void _cmd_ErrorDataReceived(object sender, DataReceivedEventArgs e)
        {
            UpdateConsole(e.Data, Brushes.Red);
        }

        void _cmd_Exited(object sender, EventArgs e)
        {
            _cmd.OutputDataReceived -= new DataReceivedEventHandler(_cmd_OutputDataReceived);
            _cmd.Exited -= new EventHandler(_cmd_Exited);
        }

        private void ScrollViewer_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            outputViewer.ScrollToBottom();
        }

        private void input_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.Key)
            {
                case Key.Enter:
                    _cmd.StandardInput.WriteLine(input.Text);
                    input.Text = "";
                    break;
                case Key.Escape:
                    input.Text = "";
                    break;
            }
        }

        private void UpdateConsole(string text)
        {
            UpdateConsole(text, null);
        }

        private void UpdateConsole(string text, Brush color)
        {
            if (!output.Dispatcher.CheckAccess())
            {
                output.Dispatcher.Invoke(
                        new Action(
                                () =>
                                {
                                    WriteLine(text, color);
                                }
                            )
                    );
            }
            else
            {
                WriteLine(text, color);
            }
        }

        private void WriteLine(string text, Brush color)
        {
            if (text != null)
            {
                Span line = new Span();
                if (color != null)
                {
                    line.Foreground = color;
                }
                foreach (string textLine in text.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
                {
                    line.Inlines.Add(new Run(textLine));
                }
                line.Inlines.Add(new LineBreak());
                output.Inlines.Add(line);
            }
        }

        Process _cmd;
    }
}
4
ответ дан 14 December 2019 в 19:06
поделиться

Да - создайте процесс, используя Process.Start (ProcessStartInfo) , установив для RedirectStandardOutput (и, возможно, RedirectStandardError ) значение true и UseShellExecute ] на false в ProcessStartInfo , описывающей процесс, который вы хотите запустить.

Затем вы можете либо читать напрямую из Process.StandardOutput и Process.StandardError (в отдельных потоках, чтобы ничего не блокировалось, если процесс заполняет свой выходной буфер), либо подписаться на Событие Process.OutputDataReceived и вызов Process.BeginOutputReadLine (и эквивалент для стандартной ошибки). В MSDN есть образцы всего этого.

Обратите внимание, что в любом случае вы будете получать данные в потоке, отличном от потока пользовательского интерфейса, поэтому вы захотите использовать Control.Invoke / Control.BeginInvoke для маршалинга обратно в поток пользовательского интерфейса перед добавлением текста в TextBox.

1
ответ дан 14 December 2019 в 19:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: