Frage

Ich möchte ein externes Kommandozeilen-Programm von meinem Mono / .NET App auszuführen. Zum Beispiel würde Ich mag laufen mencoder . Ist es möglich:

  1. Um die Befehlszeilen-Shell Ausgabe zu erhalten, und schreiben Sie es auf meinem Textfeld?
  2. , um den Zahlenwert zu erhalten, einen Fortschrittsbalken zu zeigen, mit der Zeit vergangen ist?
War es hilfreich?

Lösung

Wenn Sie erstellen Ihre Process Objektsatz StartInfo entsprechend:

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

dann den Prozess starten und liest daraus:

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

Sie können int.Parse() oder int.TryParse() verwenden, um die Strings in numerische Werte umzuwandeln. Sie können einige String-Manipulation zu tun haben, zuerst, wenn es ungültige numerische Zeichen in den Streichern sind Sie lesen.

Andere Tipps

Sie können die Ausgabe verarbeiten synchron oder asynchron .

1: Synchrone Beispiel

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

Hinweis , dass es besser ist, beide zu verarbeiten Ausgang und Fehler : Sie müssen separat behandelt werden

.

(*) Für einige Befehle (hier StartInfo.Arguments) müssen Sie die /c hinzufügen Richtlinie , sonst der Prozess gefriert in der WaitForExit().

2: Asynchronous Beispiel

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

Wenn Sie nicht brauchen, komplizierte Operationen mit dem Ausgang zu tun, können Sie Bypass der Output-Methode, nur die Handler hinzugefügt direkt inline:

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

In Ordnung, für jeden, den beiden Fehler und Ausgänge lesen, aber bekommt Deadlocks mit einem der Lösungen, in anderen Antworten zur Verfügung gestellt (wie ich), hier ist eine Lösung, dass ich nach dem Lesen MSDN Erklärung für StandardOutput Eigenschaft gebaut.

Antwort basiert auf T30 Code:

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

Der Standard-.NET-Weg, dies zu tun, ist aus dem Prozess lesen StandardOutput Stream. Es gibt ein Beispiel in der verknüpften MSDN-Dokumentation. Ähnliche, können Sie lesen von Standarderror und schreiben auf StandardInput .

  1. Es ist möglich, den Befehlszeilen-Shell Ausgang eines Prozesses zu erhalten, wie hier beschrieben: http://www.c-sharpcorner.com/UploadFile/edwinlima/SystemDiagnosticProcess12052005035444AM/SystemDiagnosticProcess.aspx

  2. Dies ist abhängig von mencoder. Wenn es diesen Status in der Befehlszeile ouputs dann ja:)

können Sie verwenden den gemeinsamen Speicher für die 2-Prozesse bis hin zu kommunizieren Besuche MemoryMappedFile

Sie werden in erster Linie eine Memory-Mapped-Datei mmf in dem übergeordneten Prozess erstellen mit „using“ Anweisung dann den zweiten Prozess erstellen, bis es beendet und lassen Sie es das Ergebnis an den mmf schreibt BinaryWriter verwenden, lesen Sie dann das Ergebnis aus dem mmf mit der übergeordnete Prozess, können Sie auch den Namen mmf Befehlszeilenargumente oder Fest Code übergeben Sie es.

stellen Sie sicher, wenn die zugeordnete Datei in dem übergeordneten Prozess mit, dass Sie dem Kind Prozess schreibt das Ergebnis in die zugeordnete Datei, bevor die abgebildete Datei im übergeordneten Prozess freigegeben wird

Beispiel: Eltern-Prozess

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

Child Prozess

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

Mit dieser Probe verwenden, müssen Sie in eine Lösung mit 2-Projekte erstellen, dann nehmen Sie die Build-Ergebnis des Kindes Prozess von% childDir% / bin / debug und kopieren Sie sie in% Parent% / bin / debug läuft dann das übergeordnete Projekt

childDir und parentDirectory sind die Ordnernamen Ihrer Projekte auf dem PC Glück:)

Wie ein Verfahren (wie eine Fledermaus-Datei, Perl-Skript, Konsolenprogramm) starten und haben die Standardausgabe auf einem Fenster angezeigt bilden:

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

Sie können ProcessCaller finden auf diesen Link: einen Prozess starten und die Standardausgabe Anzeige

Die Lösung, die für mich in Win und Linux gearbeitet ist die folgende

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

Sie können Prozessausgangs melde dich hier unten Code verwendet:

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) { 
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top