C# - Асинхронное Чтение Текста Из Окна Консоли
Привет!
У меня есть приложение C#, которое взаимодействует с консольным окном (через SetForegroundWindow и sendKeys). Это отлично работает, и я использую его для отправки команд в окно консоли (я также запускаю другую программу DOS внутри командной строки).
Проблема в том, что я хотел бы прочитать Результат после каждой команды!
Я пытался перенаправить стандартный вывод, но это не работает, так как мне нужно делать это с открытым окном в течение длительного времени.
Может ли кто-нибудь указать мне правильное направление? Можно ли этого вообще добиться?
Я подозреваю, что это можно сделать с помощью некоторых вызовов API, но это выходит за рамки моих текущих знаний.
С уважением
/Кипарисы
Andy Lanng
Значит окна должны быть открыты? разве вы не можете запустить команду cmd в коде, чтобы терминал не подключался?
Matbe это linux-сторона моего выхода, но я думаю, что это гораздо проще, если терминал не используется. Во всяком случае - на этот случай я отвечу ниже
MrFinch
Привет, Энди!
Спасибо за быстрый ответ. Ну, я начинаю "другую" программу с самого начала. cmd.exe команда и от этого мне нужно отправлять и получать данные. Я не совсем понимаю, что ты имеешь в виду, говоря, что не пользуешься терминалом. Не могли бы вы объяснить, пожалуйста! Боюсь, что Linux здесь не подходит.
Andy Lanng
Это только терминология терминала linux - я объясняю немного лучше в своем ответе. Дайте мне знать, если вы нуждаетесь в разъяснении, но, похоже, ответ соответствует вашим потребностям :)
MrFinch
Еще раз привет!
Спасибо, что помог мне. Это почти работает, мне пришлось сделать эти модификации:
startInfo.RedirectStandardOutput = true;// false;
startInfo.RedirectStandardError = true; // false;
startInfo.RedirectStandardInput = true; // new
Но я могу запустить приложение только один раз с помощью одной команды (процесс, похоже, закрывается сразу после этого). Мне нужно уметь посылать несколько команд и читать несколько ответов. Я попытался разорвать этот процесс и начать делать их публичными, но это не помогло.
Что Касается Сайпрес
Andy Lanng
ах, тогда вам нужно будет передать буферы потоком. Это позволит сохранить процесс открытым. Я обновлю информацию с ответом.
извините за редиректы - мой код делает что - то немного другое- вы правы
Andy Lanng
С другой стороны: вы уверены, что процесс ждет? Разве вы не можете просто начать процесс несколько раз?
Могу я посмотреть ваши команды, пожалуйста ^_^
MrFinch
Еще раз привет!
Мои команды выглядят примерно так. RunExternalApplication.exe, listUnit, ReadCommand, WriteCommand и т. д.
После каждой отправленной команды приложение возвращается с информацией об успехе и фактическими данными (вот почему мне нужно держать "линию" открытой).
Нет, я не могу (или, скорее, не хочу) входить в систему каждый раз, так как для завершения каждой процедуры входа в систему может потребоваться до одной минуты (глупая система, которая взаимодействует с другим оборудованием).
Поэтому, если это возможно, однократный вход в систему, сопровождаемый несколькими командами, имеет большое значение.
Тем не менее, спасибо за разъяснение того, как работает перенаправление, очень ценю.
С уважением
Кипарисы
Andy Lanng
Хм, ладно. процесс.WaitForExit();" будет ждать, пока мы не закроем трубы, которые мы читаем. Я опубликую второй ответ с асинхронным материалом.
Я не буду делать это слишком кричащим - вы можете это сделать ;)
PS: один из способов сделать его очень ярким-это использовать Observable.FromEvent. Загляни в него ^_^
Andy Lanng
omg - первый раз, когда я был в топ-5! и ты забрал все это #плач-теперь #justkidding
:П
Я вернусь туда, если вы примете следующее решение ^_^
MrFinch
Ух ты!
Я впечатлен всеми усилиями, которые вы вложили в это дело.
Я должен признать, что ты не в моей лиге, и мне нужно кое-что наверстать. ;)
Я был вынужден сделать некоторые небольшие корректировки, чтобы сделать ваш код компилируемым, и, возможно, я все испортил (я уверен, что ошибки на моей стороне):
Я заменил выходной очереди 'с 'Выход', подтягивались _process.Start() перед '_inputStreamWriter = _process.StandardInput;' строка.
Процесс все еще "кажется" закрытым, потому что я читаю действительные данные только в первый раз, и независимо от того, сколько раз я запускаю функцию SendCommand, она, кажется, не "кусается". Я попытался отладить, но так и не нашел, в чем именно заключается проблема. Когда я отлаживаю, я получаю здесь исключение:
если (args.Data == null)
{
//труба закрылась, то есть процесс закончился
_waitHandles[1].Set();
}
И чтобы избавиться от этого мне нужно было добавить вот это:
_waitHandles[1] = новый ManualResetEvent(false);
Не поймите меня неправильно, я действительно ценю вашу помощь, я просто пытаюсь объяснить свою точку зрения. Я уверен, что проблема где-то на моей стороне.
Завтра я буду копать глубже.
Хороших выходных.
Andy Lanng
Ах, я должен был создать экземпляр waithandles перед началом чтения буфера.
Я тоже поиграю с ним и посмотрю, почему командир не работает.
PS: Если вы получаете _waitHandles[0].Set(); то программа вышла
MrFinch
А, может быть, это все и объясняет. Я замечаю, что появляется окно консоли, и когда я закрываюсь, я могу прочитать первый результат. Я думаю, что именно поэтому SendCommand не работает, "процесс" или консоль закрыты. Я пытаюсь понять, почему и как это предотвратить.
Спасибо за помощь.
MrFinch
Еще раз привет!
Я даю вам 4 за быстрый ответ и за полный класс. Это не совсем так, как я хочу, но это может быть внутренней проблемой моего приложения.
Andy Lanng
Звучит справедливо. Если у меня будет время сегодня я попытаюсь найти эту неуловимую пятую звезду ;)
MrFinch
Отлично! Хм, мне было интересно. Как я уже сказал, Я подозреваю, что проблема может быть в моем внешнем приложении, но не должен иметь возможности читать и записывать в стандартное окно cmd? Я имею в виду если я просто пройду мимо cmd.exe как командование? Однако и это не работает. Я могу читать только один раз после того, как окно cmd будет закрыто (мной). Может быть, это может быть ключом к тому, что происходит...
Твоя "пятерка" приближается тааак ;)