C # Shell - перенаправление ввода-вывода - PullRequest
1 голос
/ 30 июня 2009

Я пишу заменяющую оболочку Windows в C #, и функция, которую я сейчас реализую, заключается в том, чтобы все операции ввода-вывода были в одном и том же окне оболочки, т. Е. Не открывать cmd.exe в другом окне.

Прямо сейчас у меня есть частичное решение для вывода. Это мой код (где p - это запущенный процесс):

while ( !p.HasExited ) {
    /* ... - irrelevant */
    if ( redirect ) {
        try {
            p.BeginOutputReadLine();
        } catch { }
    }
}

Процесс настроен со всеми правильными свойствами, такими как UseShellExecute = False, RedirectStandard{Input, Output, Error} = True, и обработчики событий настроены правильно, но это противоречиво.

Я пытался убрать try / catch (что я знаю, что это очень плохая практика) и использовал занятый bool, который устанавливается в false при запуске обработчика, но по какой-то причине я все еще получаю InvalidOperationException на p .BeginOutputReadLine () - указывает, что асинхронная операция уже запущена.

Буду признателен за любую помощь, даже если она потребует совершенно иного решения, чем приведенное выше, а не просто исправления.

Спасибо.

РЕДАКТИРОВАТЬ : Вот код, который запускает процесс:

if (redirect)
{
    p.StartInfo.RedirectStandardOutput = true;
    p.StartInfo.RedirectStandardError = true;
    p.StartInfo.RedirectStandardInput = true;
    p.StartInfo.UseShellExecute = false;
    p.OutputDataReceived += new DataReceivedEventHandler(redirectHandler_StdOut);
    p.ErrorDataReceived += new DataReceivedEventHandler(redirectHandler_StdErr);
}
p.Start();

Кроме того, я понял, что не объясняю, что я имею в виду под непоследовательным. Как говорится, картинка стоит 2^3 слова:

screenshot

1 Ответ

3 голосов
/ 30 июня 2009

Методы с префиксом Begin обычно выполняются асинхронно. Это то, что вы хотите? Потому что кажется, что цикл выполняется настолько быстро, насколько это возможно, вызывая все больше и больше BeginOutputReadLine (потому что вызов возвращается немедленно, прежде чем он будет выполнен, и цикл возвращается к следующей итерации).

Вы можете вызвать ReadLine в потоке StandardOutput для синхронного решения. Или:

    while ( !p.HasExited ) {
        /* ... - irrelevant */
        if ( redirect && !busy ) {
            try {
                busy = true;
                p.BeginOutputReadLine();
            } catch { }
        }
    }
   ////In the method that gets called upon completion of BeginOutputReadLine
   busy = false;

Имейте это в виду, хотя (из MSDN):

при асинхронных операциях чтения начать, обработчик события называется каждый раз связанный процесс пишет строку текста к его Стандартный поток вывода.

Вы можете отменить асинхронное чтение операция, вызвав CancelOutputRead. Операция чтения может быть отменена вызывающая сторона или обработчик события. После отмены вы можете позвонить BeginOutputReadLine снова возобновить асинхронные операции чтения.

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

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