Domanda

Vorrei eseguire un programma da riga di comando esterno dalla mia app Mono/.NET.Ad esempio, vorrei correre mencoder.È possibile:

  1. Per ottenere l'output della shell della riga di comando e scriverlo nella mia casella di testo?
  2. Per ottenere che il valore numerico mostri una barra di avanzamento con il tempo trascorso?
È stato utile?

Soluzione

Quando si crea l'oggetto Process set StartInfo in modo appropriato:

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

quindi avviare il processo e leggere da esso:

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

È possibile utilizzare int.Parse() o int.TryParse() per convertire le stringhe in valori numerici. Potrebbe essere necessario fare un po 'manipolazione di stringhe primo luogo se ci sono caratteri numerici validi nelle stringhe che si leggono.

Altri suggerimenti

È possibile elaborare l'output in modo sincrono O in modo asincrono.

1:Esempio sincrono

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 che è meglio elaborarli entrambi produzione E errori:devono essere gestiti separatamente.

(*) Per alcuni comandi (qui StartInfo.Arguments) è necessario aggiungere il /c direttiva, altrimenti il ​​processo si blocca nel file WaitForExit().

2:Esempio asincrono

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

Se non hai bisogno di complicare operazioni con l'output, puoi bypassare il metodo OutputHandler, aggiungendo semplicemente i gestori direttamente in linea:

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

Bene, per chi vuole sia gli errori e uscite leggere, ma ottiene deadlock con una qualsiasi delle soluzioni, a condizione che in altre risposte (come me), ecco una soluzione che ho costruito dopo la lettura MSDN spiegazione per la proprietà StandardOutput.

risposta è basato sul codice di 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);
}

Il modo .NET standard di fare questo è quello di leggere dal Processo rel StandardOutput flusso. C'è un esempio nella documentazione MSDN collegate. Simile, è possibile leggere da StandardError , e scrittura a StandardInput .

  1. E 'possibile ottenere il risultato shell linea di comando di un processo come descritto qui: http://www.c-sharpcorner.com/UploadFile/edwinlima/SystemDiagnosticProcess12052005035444AM/SystemDiagnosticProcess.aspx

  2. Questo dipende mencoder. Se USCITE questo stato sulla riga di comando allora sì:)

è possibile utilizzare la memoria condivisa per i 2 processi di comunicare attraverso, controlla MemoryMappedFile

creerai principalmente una memoria mappata mmf file nel processo padre con "utilizzando" l'istruzione quindi creare il secondo processo fino a che non termina e lascia che scrivere il risultato al mmf utilizzando BinaryWriter, poi leggere il risultato dalla mmf utilizzando il processo padre, si può anche passare il nome mmf utilizzando gli argomenti della riga di comando o di difficile codice di esso.

assicurarsi che quando si utilizza il file mappato nel processo padre che a fare la scrittura processo figlio il risultato al file mappato prima che il file mappato viene rilasciato nel processo padre

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

processo Bambino

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

Per utilizzare questo esempio, è necessario creare una soluzione con 2 progetti all'interno, poi si prende il risultato build del processo figlio da% childDir% / bin / debug e copiarlo% ParentDirectory% / bin / debug quindi eseguire il progetto principale

childDir e parentDirectory sono i nomi delle cartelle dei vostri progetti sul pc buona fortuna:)

Come avviare un processo (ad esempio un file bat, script perl, programma di console) e hanno il suo standard output visualizzato su un Windows Form:

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

Si possono trovare ProcessCaller su questo link: Il lancio di un processo e la visualizzazione suo standard di uscita

La soluzione che ha funzionato per me in vittoria e Linux è il seguente

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

È possibile accedere uscita di processo utilizzando il codice qui sotto:

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) { 
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top