Pregunta

Me gustaría ejecutar un programa de línea de comando externo de mi Mono / .NET aplicación. Por ejemplo, me gustaría correr MEncoder . ¿Es posible:

  1. Para obtener la salida de la shell de línea de comandos, y la escribiré en mi cuadro de texto?
  2. Para obtener el valor numérico para mostrar una barra de progreso con el tiempo transcurrido?
¿Fue útil?

Solución

Al crear su Process conjunto de objetos StartInfo apropiada:

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

a continuación, iniciar el proceso y leer de él:

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

Se puede utilizar int.Parse() o int.TryParse() para convertir las cadenas a valores numéricos. Puede que tenga que hacer un poco de manipulación de cadenas primero si hay caracteres numéricos no válidos en las cuerdas que lee.

Otros consejos

Se puede procesar su salida sincrónicamente o asíncrona .

1: ejemplo Synchronous

static void runCommand()
{
    Process process = new Process();
    process.StartInfo.FileName = "cmd.exe";
    process.StartInfo.Arguments = "/c DIR"; // Note the /c command (*)
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardOutput = true;
    process.StartInfo.RedirectStandardError = true;
    process.Start();
    //* Read the output (or the error)
    string output = process.StandardOutput.ReadToEnd();
    Console.WriteLine(output);
    string err = process.StandardError.ReadToEnd();
    Console.WriteLine(err);
    process.WaitForExit();
}

Nota: que es mejor para procesar tanto salida y errores que debe ser manejado por separado

.

(*) Para algunos comandos (aquí StartInfo.Arguments) debe agregar el /c Directiva , lo contrario el proceso se congela en el WaitForExit().

2: ejemplo asíncrono

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 your output and error (asynchronous) handlers
    process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
    process.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler);
    //* Start process and handlers
    process.Start();
    process.BeginOutputReadLine();
    process.BeginErrorReadLine();
    process.WaitForExit();
}

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

Si usted no necesita hacer operaciones complicar con la salida, puede omitir el método OutputHandler, simplemente añadiendo los controladores directamente en línea:

//* Set your output and error (asynchronous) handlers
process.OutputDataReceived += (s, e) => Console.WriteLine(e.Data);
process.ErrorDataReceived += (s, e) => Console.WriteLine(e.Data);

Muy bien, para cualquier persona que busca que ambos errores y salidas de leer, pero obtiene los puntos muertos con cualquiera de las soluciones, siempre en otras respuestas (como yo), aquí es una solución que he construido después de leer MSDN explicación de la propiedad StandardOutput.

La respuesta se basa en el código del 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);
}

La forma .NET estándar de hacer esto es para leer desde el Proceso StandardOutput corriente. Hay un ejemplo en la documentación de MSDN vinculados. Similares, se puede leer en StandardError , y escritura a StandardInput .

  1. Es posible obtener la salida shell de línea de comando de un proceso como se describe aquí: http://www.c-sharpcorner.com/UploadFile/edwinlima/SystemDiagnosticProcess12052005035444AM/SystemDiagnosticProcess.aspx

  2. Esto depende de mencoder. Si ouputs este estado en la línea de comandos, entonces sí:)

Puede utilizar la memoria compartida para los 2 procesos se comuniquen a través, echa un vistazo a MemoryMappedFile

se creará sobre todo una memoria mapeada mmf archivo en el proceso principal mediante el "uso" comunicado a continuación, crear el segundo proceso hasta que se termina y se deja escribir el resultado a la mmf usando BinaryWriter, a continuación, lea el resultado del uso de mmf el proceso padre, también puede pasar el nombre mmf usando los argumentos de línea de comandos o código sea difícil a él.

asegúrese de que cuando se utiliza el archivo asignado en el proceso principal que realice el proceso hijo grabar el resultado en el archivo asignado antes de que el archivo de mapeado se libera en el proceso padre

Ejemplo: proceso padre

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

El proceso secundario

    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 utilizar este ejemplo, usted tendrá que crear una solución con 2 proyectos en el interior, entonces se toma el resultado de la acumulación del proceso hijo de% childDir% / bin / debug y copiarlo% ParentDirectory% / bin / debug a continuación, ejecutar el proyecto principal

childDir y parentDirectory son los nombres de las carpetas de sus proyectos en el PC buena suerte:)

¿Cómo poner en marcha un proceso (como un archivo bat, script de perl, programa de consola) y tendrá su salida estándar visualiza en una ventana de formulario:

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

Se puede encontrar ProcessCaller en este enlace: Lanzamiento de un proceso y mostrando su salida estándar

La solución que funcionó para mí en la victoria y Linux es el siguiente

// GET api/values
        [HttpGet("cifrado/{xml}")]
        public ActionResult<IEnumerable<string>> Cifrado(String xml)
        {
            String nombreXML = DateTime.Now.ToString("ddMMyyyyhhmmss").ToString();
            String archivo = "/app/files/"+nombreXML + ".XML";
            String comando = " --armor --recipient bibankingprd@bi.com.gt  --encrypt " + archivo;
            try{
                System.IO.File.WriteAllText(archivo, xml);                
                //String comando = "C:\\GnuPG\\bin\\gpg.exe --recipient licorera@local.com --armor --encrypt C:\\Users\\Administrador\\Documents\\pruebas\\nuevo.xml ";
                ProcessStartInfo startInfo = new ProcessStartInfo() {FileName = "/usr/bin/gpg",  Arguments = comando }; 
                Process proc = new Process() { StartInfo = startInfo, };
                proc.StartInfo.RedirectStandardOutput = true;
                proc.StartInfo.RedirectStandardError = true;
                proc.Start();
                proc.WaitForExit();
                Console.WriteLine(proc.StandardOutput.ReadToEnd());
                return new string[] { "Archivo encriptado", archivo + " - "+ comando};
            }catch (Exception exception){
                return new string[] { archivo, "exception: "+exception.ToString() + " - "+ comando };
            }
        }

Puede conectarse salida del proceso mediante el siguiente código:

ProcessStartInfo pinfo = new ProcessStartInfo(item);
pinfo.CreateNoWindow = false;
pinfo.UseShellExecute = true;
pinfo.RedirectStandardOutput = true;
pinfo.RedirectStandardInput = true;
pinfo.RedirectStandardError = true;
pinfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
var p = Process.Start(pinfo);
p.WaitForExit();
Process process = Process.Start(new ProcessStartInfo((item + '>' + item + ".txt"))
{
    UseShellExecute = false,
    RedirectStandardOutput = true
});
process.WaitForExit();
string output = process.StandardOutput.ReadToEnd();
if (process.ExitCode != 0) { 
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top