c# - Process.start: como obter a saída?




4 Answers

Quando você cria seu objeto Process defina StartInfo apropriadamente:

var proc = new Process 
{
    StartInfo = new ProcessStartInfo
    {
        FileName = "program.exe",
        Arguments = "command line arguments to your executable",
        UseShellExecute = false,
        RedirectStandardOutput = true,
        CreateNoWindow = true
    }
};

então inicie o processo e leia:

proc.Start();
while (!proc.StandardOutput.EndOfStream)
{
    string line = proc.StandardOutput.ReadLine();
    // do something with line
}

Você pode usar int.Parse() ou int.TryParse() para converter as cadeias em valores numéricos. Você pode ter que fazer alguma manipulação de seqüência de caracteres primeiro se houver caracteres numéricos inválidos nas seqüências de caracteres que você lê.

Eu gostaria de executar um programa de linha de comando externo do meu aplicativo Mono / .NET. Por exemplo, eu gostaria de rodar o mencoder . É possível:

  1. Para obter a saída do shell da linha de comando e gravá-la na minha caixa de texto?
  2. Para obter o valor numérico para mostrar uma barra de progresso com o tempo decorrido?



Tudo bem, para qualquer um que deseje leitura de Erros e Saídas, mas receba deadlocks com qualquer uma das soluções, fornecidas em outras respostas (como eu), aqui está uma solução que construí depois de ler a explicação do MSDN para a propriedade StandardOutput.

A resposta é baseada no código do T30:

static void runCommand()
{
    //* Create your Process
    Process process = new Process();
    process.StartInfo.FileName = "cmd.exe";
    process.StartInfo.Arguments = "/c DIR";
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardOutput = true;
    process.StartInfo.RedirectStandardError = true;
    //* Set ONLY ONE handler here.
    process.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler);
    //* Start process
    process.Start();
    //* Read one element asynchronously
    process.BeginErrorReadLine();
    //* Read the other one synchronously
    string output = process.StandardOutput.ReadToEnd();
    Console.WriteLine(output);
    process.WaitForExit();
}

static void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine) 
{
    //* Do your stuff with the output (write to console/log/StringBuilder)
    Console.WriteLine(outLine.Data);
}



você pode usar memória compartilhada para os 2 processos para se comunicar, confira MemoryMappedFile

você criará principalmente um arquivo de memória mapeado mmf no processo pai usando a instrução "using" e então criará o segundo processo até que ele termine e deixe gravar o resultado para o mmf usando BinaryWriter , então leia o resultado do mmf usando o processo pai , você também pode passar o nome mmf usando argumentos de linha de comando ou codificar isso.

Verifique se, ao usar o arquivo mapeado no processo pai, você faz o processo filho gravar o resultado no arquivo mapeado antes que o arquivo mapeado seja liberado no processo pai

Exemplo: processo pai

    private static void Main(string[] args)
    {
        using (MemoryMappedFile mmf = MemoryMappedFile.CreateNew("memfile", 128))
        {
            using (MemoryMappedViewStream stream = mmf.CreateViewStream())
            {
                BinaryWriter writer = new BinaryWriter(stream);
                writer.Write(512);
            }

            Console.WriteLine("Starting the child process");
            // Command line args are separated by a space
            Process p = Process.Start("ChildProcess.exe", "memfile");

            Console.WriteLine("Waiting child to die");

            p.WaitForExit();
            Console.WriteLine("Child died");

            using (MemoryMappedViewStream stream = mmf.CreateViewStream())
            {
                BinaryReader reader = new BinaryReader(stream);
                Console.WriteLine("Result:" + reader.ReadInt32());
            }
        }
        Console.WriteLine("Press any key to continue...");
        Console.ReadKey();
    }

Processo filho

    private static void Main(string[] args)
    {
        Console.WriteLine("Child process started");
        string mmfName = args[0];

        using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting(mmfName))
        {
            int readValue;
            using (MemoryMappedViewStream stream = mmf.CreateViewStream())
            {
                BinaryReader reader = new BinaryReader(stream);
                Console.WriteLine("child reading: " + (readValue = reader.ReadInt32()));
            }
            using (MemoryMappedViewStream input = mmf.CreateViewStream())
            {
                BinaryWriter writer = new BinaryWriter(input);
                writer.Write(readValue * 2);
            }
        }

        Console.WriteLine("Press any key to continue...");
        Console.ReadKey();
    }

para usar este exemplo, você precisará criar uma solução com dois projetos dentro, então você pega o resultado da compilação do processo filho de% childDir% / bin / debug e copia para% parentDirectory% / bin / debug, em seguida, executa o projeto pai

childDir e parentDirectory são os nomes das pastas dos seus projetos no pc boa sorte :)




Como iniciar um processo (como um arquivo bat, script perl, console de programa) e ter sua saída padrão exibida em um formulário do windows:

processCaller = new ProcessCaller(this);
//processCaller.FileName = @"..\..\hello.bat";
processCaller.FileName = @"commandline.exe";
processCaller.Arguments = "";
processCaller.StdErrReceived += new DataReceivedHandler(writeStreamInfo);
processCaller.StdOutReceived += new DataReceivedHandler(writeStreamInfo);
processCaller.Completed += new EventHandler(processCompletedOrCanceled);
processCaller.Cancelled += new EventHandler(processCompletedOrCanceled);
// processCaller.Failed += no event handler for this one, yet.

this.richTextBox1.Text = "Started function.  Please stand by.." + Environment.NewLine;

// the following function starts a process and returns immediately,
// thus allowing the form to stay responsive.
processCaller.Start();    

Você pode encontrar o ProcessCaller neste link: Iniciando um processo e exibindo sua saída padrão




Related