ProcessInfo и RedirectStandardOutput - PullRequest
27 голосов
/ 18 июля 2009

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

string assemblyLocation = Assembly.GetExecutingAssembly().Location;

Process process = new Process
{
    ProcessStart =
    {
        RedirectStandardOutput = true,
        UseShellExecute = false,
        WindowStyle = ProcessWindowStyle.Hidden,
        Arguments = arg,
        FileName = assemblyLocation.Substring(0, assemblyLocation.LastIndexOf("\\")) + "\\ffmpeg.exe",
        CreateNoWindow = true
    }
};

process.Start();

Console.WriteLine(process.StandardOutput.ReadToEnd());

process.WaitForExit();

В идеале мне бы хотелось, чтобы выходной сигнал изменялся в процессе, к которому я обращаюсь, или данные попадают в считыватель, и я получаю с него события.

Любая помощь была бы отличной, я чувствую, что это вопрос новичка, но, похоже, что-то упустил.

Ответы [ 6 ]

48 голосов
/ 18 июля 2009

Я испытал это раньше. Иногда способ, которым вызываемый вами процесс выводит данные на консоль, несовместим с таким перенаправлением вывода. Мне повезло, что я смог изменить внешний процесс, чтобы обойти это.

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

EDIT:

Я пошел и вытащил блок кода, который я использовал для этого. Это в приложении WPF, которое перенаправляет вывод процесса в окно. Обратите внимание на привязку события. Поскольку это WPF, я должен вызвать мой вызов для записи данных. Поскольку вы не беспокоитесь о блокировке, вы можете просто заменить это на:

Console.WriteLine(e.Data);

Надеюсь, это поможет!

    private static void LaunchProcess()
    {
        Process build = new Process();
        build.StartInfo.WorkingDirectory =  @"dir";
        build.StartInfo.Arguments = "";
        build.StartInfo.FileName = "my.exe";

        build.StartInfo.UseShellExecute = false;
        build.StartInfo.RedirectStandardOutput = true;
        build.StartInfo.RedirectStandardError = true;
        build.StartInfo.CreateNoWindow = true;
        build.ErrorDataReceived += build_ErrorDataReceived;
        build.OutputDataReceived += build_ErrorDataReceived;
        build.EnableRaisingEvents = true;
        build.Start();
        build.BeginOutputReadLine();
        build.BeginErrorReadLine();
        build.WaitForExit();
    }

    // write out info to the display window
    static void build_ErrorDataReceived(object sender, DataReceivedEventArgs e)
    {
        string strMessage = e.Data;
        if (richTextBox != null && !String.Empty(strMessage))
        {
            App.Instance.Dispatcher.BeginInvoke(DispatcherPriority.Send, (ThreadStart)delegate()
            {
                Paragraph para = new Paragraph(new Run(strMessage));
                para.Margin = new Thickness(0);
                para.Background = brushErrorBrush;
                box.Document.Blocks.Add(para);
            });
       }
    } 
21 голосов
/ 18 июля 2009

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

ProcessStartInfo info = new ProcessStartInfo(...)
info.UseShellExecute = false;
info.RedirectStandardOutput = true;
info.RedirectStandardError = true;

Process p = Process.Start(info);
p.OutputDataReceived += p_OutputDataReceived;
p.ErrorDataReceived += p_ErrorDataReceived;

p.BeginOutputReadLine();
p.BeginErrorReadLine();
p.WaitForExit();

..

void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
  Console.WriteLine("Received from standard out: " + e.Data);
}

void p_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
  Console.WriteLine("Received from standard error: " + e.Data);
}

См. Событие OutputDataReceived off Процесс для получения дополнительной информации.

11 голосов
/ 29 августа 2010

Использование лямбда-выражений и т.д .:

var info = new ProcessStartInfo(path)
{
    RedirectStandardError = true,
    RedirectStandardOutput = true,
    UseShellExecute = false,
    Verb = "runas",
};

var process = new Process
{
    EnableRaisingEvents = true,
    StartInfo = info
};

Action<object, DataReceivedEventArgs> actionWrite = (sender, e) =>
{
    Console.WriteLine(e.Data);
};

process.ErrorDataReceived += (sender, e) => actionWrite(sender, e);
process.OutputDataReceived += (sender, e) => actionWrite(sender, e);

process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
4 голосов
/ 24 ноября 2011

Интересно, что вы не можете читать из стандартного вывода и стандартной ошибки одновременно:

если вы перенаправляете как стандартный вывод, так и стандартную ошибку, а затем пытаетесь прочитать оба, для Пример использования следующего кода C #.

[C #]

string output = p.StandardOutput.ReadToEnd ();

string error = p.StandardError.ReadToEnd ();

p.WaitForExit ();

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

http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandardoutput(v=vs.71).aspx

1 голос
/ 26 ноября 2013

текущий код работал в VS2010

void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
    {
        if (String.IsNullOrEmpty(e.Data) == false)
        {
            new Thread(() =>
            {
                this.Dispatcher.Invoke(new Action(() =>
                {
                    // Add you code here
                }));
            }).Start();
        }
    }
0 голосов
/ 31 октября 2013

Убедитесь, что ожидаемый вывод не отправляется на выход StandardError вместо вывода StandardOutput

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