Ожидание выполнения команд - PullRequest
0 голосов
/ 23 февраля 2011

Я работаю с winform, который запускает cmd в фоновом режиме, перенаправляя ввод и вывод асинхронно.

В настоящее время winform выполняет итерацию по массиву команд, записывая каждую в cmd через StreamWriter, на который перенаправляется StandardInput. Как я могу заставить цикл ждать до завершения текущей команды в cmd перед записью следующей строки в?

РЕДАКТИРОВАТЬ: Я вынул весь свой реальный код проекта и заменил его на урезанную версию того, что я пытаюсь сделать, включая только компоненты моего проекта, относящиеся к моему вопросу .

public partial class Form1 : Form
{

    public delegate void WriteToConsoleMethod(string text);
    Process _process;

    string[] _commands = 
    {
        "echo hello world",
        "echo my name is T.K.",
        "echo Here is a list of commands"
    };
    public Form1()
    {
        InitializeComponent();
        ProcessStartInfo processStartInfo = new ProcessStartInfo("cmd")
        {
            RedirectStandardError = true,
            RedirectStandardInput = true,
            RedirectStandardOutput = true,
            UseShellExecute = false,
            CreateNoWindow = true
        };

        _process = Process.Start(processStartInfo);
        _process.OutputDataReceived += new DataReceivedEventHandler(new DataReceivedEventHandler(DataReceived_EventHandler));
        _process.ErrorDataReceived += new DataReceivedEventHandler(new DataReceivedEventHandler(DataReceived_EventHandler));
        _process.BeginErrorReadLine();
        _process.BeginOutputReadLine();
    }

    private void DataReceived_EventHandler(object sender, DataReceivedEventArgs e)
    {
        IAsyncResult result = this.BeginInvoke(new WriteToConsoleMethod(writeToConsole), new object[] { e.Data + Environment.NewLine });
        this.EndInvoke(result);
    }

    private void writeToConsole(string output)
    {
        txtbxConsole.AppendText(output);
    }

    private void btnBegin_Click(object sender, EventArgs e)
    {
        foreach (string command in _commands)
        {
            _process.StandardInput.WriteLine(command);
            // I want a way to pause here until the cmd has finished processing the command.
        }
    }
}

Ответы [ 3 ]

1 голос
/ 23 февраля 2011

Я не думаю, что есть что-то встроенное, что будет поддерживать это. Однако вы можете отправить свою собственную специальную команду, а затем подождать, пока вы не увидите это в выводе, например, что-то вроде:

    const string Separator= "---Command Completed--\xE3\xE2\xE1\xE0\xE3";   
    // Has to be something that won't occur in normal output.  

    volatile bool finished = false;

    private void button1_Click(object sender, EventArgs e)
    {         
        foreach (string command in _commands)
            Run(command);
    }

    private void writeToConsole(string output)
    {
        if (output.IndexOf(Separator) >= 0)
            finished = true;
        else
            richTextBox1.AppendText(output);
    }


    private void Run(string command)
    {
        finished = false;
        _process.StandardInput.WriteLine(command);
        _process.StandardInput.WriteLine("@echo " + Seperator);
        while (!finished)
        {
            Application.DoEvents();
            System.Threading.Thread.Sleep(100);
        }
    }

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        finished = true;
    }
0 голосов
/ 24 февраля 2011

В итоге я решил эту проблему, заключив взаимодействие с командной строкой в ​​отдельный класс, и вместо того, чтобы поддерживать одно приглашение для всех действий, я запускал другое приглашение для каждого вызова. Затем я использую WaitForExit() для синхронизации своих потоков.

После каждой команды я пишу команду exit, чтобы закрыть процесс. Я сканирую выходные данные для вызовов на выход и, когда я нахожу их, использую контекст этой строки, чтобы сохранить рабочее пространство, чтобы запрос следующей команды был сделан из того же рабочего каталога. Мне также пришлось подключить DataRectainedEventHandler, чтобы проанализировать заголовок и завершить вызовы, прежде чем пересылать EventHandlers в winform.

Что меня беспокоит в этом решении, так это то, что если вывод любого выполняемого мной процесса выводит exit, сканер вывода будет вести себя так, как если бы он нашел исходный выход. Я использовал то же решение, которое использовал sgmoore в своем ответе - я пишу exit [UNIQUE STRING] в подсказку и сканирую выходные данные, но я уверен, что это далеко не лучшая практика.

0 голосов
/ 23 февраля 2011

Если вы используете System.Diagnostics.Process, то вам, вероятно, нужно что-то вроде

ProcessStartInfo pi = new ProcessStartInfo(cmd);                
pi.Arguments = ...
pi.WorkingDirectory = ...
Process myProcess = Process.Start(pi);      
myProcess.WaitForExit();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...