#c# #process
#c# #процесс
Вопрос:
Я вызываю консольное приложение, используя класс Process. Я перенаправляю вывод в файл журнала, но в окне консоли, когда я не перенаправляю вывод, появляется больше сообщений, чем в файле журнала, когда я перенаправляю. есть идеи, почему?
ProcessStartInfo psi = new ProcessStartInfo();
string filename = @"ProgrammingMaster_LocalPowertrain.exe";
psi.FileName = filename;
string arguments = String.Format("{0} {1} false", InstanceId.ToString(), ManifestFolderPath);
psi.Arguments = arguments;
LogMessage(msgType.Warning, filename " - " arguments);
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.RedirectStandardError = true;
psi.RedirectStandardOutput = true;
FBlockProcess = new Process();
FBlockProcess.StartInfo = psi;
FBlockProcess.OutputDataReceived = new DataReceivedEventHandler(FBlockProcess_OutputDataReceived);
FBlockProcess.ErrorDataReceived = new DataReceivedEventHandler(FBlockProcess_ErrorDataReceived);
FBlockProcess.Start();
FBlockProcess.BeginOutputReadLine();
FBlockProcess.BeginErrorReadLine();
в моем обработчике OutputDataReceived я просто добавляю строку в ConcurrentQueue
Редактировать: Я должен добавить, что я хочу записывать выходные данные в режиме реального времени или близко к нему. Запуск процесса может занять более 30 минут, я не хочу так долго ждать, чтобы увидеть, что происходит.
Обновление: После вывода первых четырех строк обработчик событий OutputDataReceived никогда не вызывается, хотя я знаю, что есть еще 10 или 15 строк, выводимых на консоль, когда я не перенаправляю. Есть идеи о том, что могло вызвать это?
Комментарии:
1. Возможно, это связано со сбросом потоков?
2. Вызываете ли вы WaitForExit() перед закрытием потоков?
3. @codymanix — нет. Я думал, что использование событий сделает это ненужным.
4. Объект process может быть собран мусором, и в этом случае вы больше не получите четности, попробуйте просто сохранить ссылку на него в статической переменной и посмотреть, исправит ли это проблему, не то, чтобы это было решением, но это легко проверить, чтобы увидеть, является ли GC виновником здесь.
5. @Lasse — Это необходимо, даже если я вижу, что процесс все еще запущен в диспетчере задач?
Ответ №1:
попробуйте этот пример:
public static void Main()
{
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c dir *.cs";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
string output = p.StandardOutput.ReadToEnd();
Console.WriteLine("Output:");
Console.WriteLine(output);
}
Обновить
Я думаю, вы можете попробовать что-то полезное здесь:
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.errordatareceived.aspx
Обновить
Я нашел эту ссылку, и «Решение 1» звучит как правильный путь:
Комментарии:
1. Таким образом, я не получу никаких выходных данных, пока они не закроются правильно?
2. Это выглядит так же, как я это делаю. вы видите, что я чего-то не понимаю?
3. проблема в том, что он компилирует все это как 1 строку, поэтому, если вы хотите просто прочитать одну строку, вы не можете…
Ответ №2:
Я столкнулся с аналогичной проблемой при попытке взаимодействия с приложением, которое требовало аутентификации. Peek () вернул бы -1 при обнаружении необычных символов (символы Юникода?) и ReadLine () также была ненадежной и в конечном итоге заблокировала бы мое приложение, поскольку, похоже, стандартный поток процесса не был закрыт.
Использование метода Read () было единственным способом гарантировать, что я получил ВСЕ строки и символы. Кроме того, использование обработчиков событий ErrorDataReceived процесса или OutputDataReceived также оказалось НЕНАДЕЖНЫМ (пропущенные строки). Ниже показано, как я решил свою проблему и обеспечил получение всех строк и символов:
process.Start();
var stdOutput = process.StandardOutput;
StringBuilder fullMessage = new StringBuilder();
while (true)
{
var character = (char)stdOutput.Read();
fullMessage.Append(character);
//Print Out All Characters
Console.Write(character);
if (fullMessage.ToString().EndsWith("Enter Password: "))
{
//Submit Password To Application
using(StreamWriter writer = process.StandardInput){
writer.Write("somepassword");
writer.Flush();
}
break;
}
}