c # ProcessStartInfo.Start - чтение вывода, но с таймаутом - PullRequest
8 голосов
/ 19 апреля 2011

Если вы хотите запустить другой процесс и подождать (с перерывом), вы можете использовать следующее (из MSDN) .

//Set a time-out value.
int timeOut=5000;
//Get path to system folder.
string sysFolder= 
    Environment.GetFolderPath(Environment.SpecialFolder.System);
//Create a new process info structure.
ProcessStartInfo pInfo = new ProcessStartInfo();
//Set file name to open.
pInfo.FileName = sysFolder + @"\eula.txt";
//Start the process.
Process p = Process.Start(pInfo);
//Wait for window to finish loading.
p.WaitForInputIdle();
//Wait for the process to exit or time out.
p.WaitForExit(timeOut);
//Check to see if the process is still running.
if (p.HasExited == false)
    //Process is still running.
    //Test to see if the process is hung up.
    if (p.Responding)
        //Process was responding; close the main window.
        p.CloseMainWindow();
    else
        //Process was not responding; force the process to close.
        p.Kill();

MessageBox.Show("Code continuing...");

Если вы хотите запустить другойобработайте и прочитайте его вывод, затем вы можете использовать следующий шаблон (из SO)

// Start the child process.
Process p = new Process();
// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "Write500Lines.exe";
p.Start();
// Do not wait for the child process to exit before
// reading to the end of its redirected stream.
// p.WaitForExit();
// Read the output stream first and then wait.
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();

Как вы можете объединить два, чтобы прочитать все входные данные, не застрять в тупике итайм-аут, если запущенный процесс идет не так?

Ответы [ 6 ]

20 голосов
/ 19 апреля 2011

Этот метод зависнет, если выходной буфер заполнен более чем 4 КБ данных. Более надежный метод состоит в том, чтобы зарегистрировать делегатов для уведомления, когда что-то записывается в выходной поток. Я уже предлагал этот метод ранее в другом посте :

ProcessStartInfo processInfo = new ProcessStartInfo("Write500Lines.exe");
processInfo.ErrorDialog = false;
processInfo.UseShellExecute = false;
processInfo.RedirectStandardOutput = true;
processInfo.RedirectStandardError = true;

Process proc = Process.Start(processInfo);

// You can pass any delegate that matches the appropriate 
// signature to ErrorDataReceived and OutputDataReceived
proc.ErrorDataReceived += (sender, errorLine) => { if (errorLine.Data != null) Trace.WriteLine(errorLine.Data); };
proc.OutputDataReceived += (sender, outputLine) => { if (outputLine.Data != null) Trace.WriteLine(outputLine.Data); };
proc.BeginErrorReadLine();
proc.BeginOutputReadLine();

proc.WaitForExit();
4 голосов
/ 19 апреля 2011

Вам не нужно объединять два - у класса Process есть событие, которое срабатывает при отправке вывода на StandardOutput - OutputDataReceived.

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

2 голосов
/ 19 апреля 2011

вы можете попробовать изменить первый метод на что-то вроде этого

Process p = Process.Start(pInfo);
string output = string.Empty;
Thread t = new Thread(() =>  output = p.StandardOutput.ReadToEnd() );
t.Start();
//Wait for window to finish loading.
p.WaitForInputIdle();
//Wait for the process to exit or time out.
p.WaitForExit(timeOut);
1 голос
/ 20 сентября 2011
void OpenWithStartInfo()
{
    ProcessStartInfo startInfo = new ProcessStartInfo("IExplore.exe", "Default2.aspx");
    startInfo.WindowStyle = ProcessWindowStyle.Minimized;
    Process p = Process.Start(startInfo);
    p.WaitForInputIdle();  
    //p.WaitForExit(2);
    p.Kill();
}
0 голосов
/ 19 апреля 2011

Вы также можете использовать APM, например:

Определение делегата для вызова ReadToEnd:

private delegate string ReadToEndDelegate();

Затем используйте делегат для вызова метода следующим образом:

ReadToEndDelegate asyncCall = reader.ReadToEnd;
IAsyncResult asyncResult = asyncCall.BeginInvoke(null, null);
asyncResult.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(10));
asyncCall.EndInvoke(asyncResult);

РЕДАКТИРОВАТЬ: обработка ошибок удалена для ясности.

0 голосов
/ 19 апреля 2011

Просто добавьте все из первого примера ниже вызова WaitForExit() ко второму примеру.

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