Подтвердить что ты не робот

ProcessInfo и RedirectStandardOutput

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

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();

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

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

4b9b3361

Ответ 1

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

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

EDIT:

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

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);
            });
       }
    } 

Ответ 2

Я не уверен, в чем проблема, в которой вы работаете, но если вы хотите действовать на выходе, как только она сгенерирована, попробуйте подключиться к событию процесса 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 событие.

Ответ 3

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

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

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

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

[С#]

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

Ответ 5

текущий код работал в 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();
        }
    }

Ответ 6

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