it-swarm-eu.dev

Jak na to: Spusťte příkazový řádek v C #, získejte výsledky STD OUT

Jak spustím program příkazového řádku z C # a získám zpět výsledky STD OUT? Konkrétně chci provést DIFF na dvou souborech, které jsou programově vybrány, a výsledky zapsat do textového pole.

435
Wing
// Start the child process.
 Process p = new Process();
 // Redirect the output stream of the child process.
 p.StartInfo.UseShellExecute = false;
 p.StartInfo.RedirectStandardOutput = true;
 p.StartInfo.FileName = "YOURBATCHFILE.bat";
 p.Start();
 // Do not wait for the child process to exit before
 // reading to the end of its redirected stream.
 // p.WaitForExit();
 // Read the output stream first and then wait.
 string output = p.StandardOutput.ReadToEnd();
 p.WaitForExit();

Kód je z MSDN .

483
Ray Jezek

Zde je rychlý příklad:

//Create process
System.Diagnostics.Process pProcess = new System.Diagnostics.Process();

//strCommand is path and file name of command to run
pProcess.StartInfo.FileName = strCommand;

//strCommandParameters are parameters to pass to program
pProcess.StartInfo.Arguments = strCommandParameters;

pProcess.StartInfo.UseShellExecute = false;

//Set output of program to be written to process output stream
pProcess.StartInfo.RedirectStandardOutput = true;   

//Optional
pProcess.StartInfo.WorkingDirectory = strWorkingDirectory;

//Start the process
pProcess.Start();

//Get program output
string strOutput = pProcess.StandardOutput.ReadToEnd();

//Wait for process to finish
pProcess.WaitForExit();
136
Jeremy

Tam byl jeden další parametr, který jsem našel užitečný, který používám k odstranění okna procesu

pProcess.StartInfo.CreateNoWindow = true;

to pomáhá skrýt černé okno konzoly před uživatelem úplně, pokud je to, co si přejete.

97
Peter Du
// usage
const string ToolFileName = "example.exe";
string output = RunExternalExe(ToolFileName);

public string RunExternalExe(string filename, string arguments = null)
{
    var process = new Process();

    process.StartInfo.FileName = filename;
    if (!string.IsNullOrEmpty(arguments))
    {
        process.StartInfo.Arguments = arguments;
    }

    process.StartInfo.CreateNoWindow = true;
    process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
    process.StartInfo.UseShellExecute = false;

    process.StartInfo.RedirectStandardError = true;
    process.StartInfo.RedirectStandardOutput = true;
    var stdOutput = new StringBuilder();
    process.OutputDataReceived += (sender, args) => stdOutput.AppendLine(args.Data); // Use AppendLine rather than Append since args.Data is one line of output, not including the newline character.

    string stdError = null;
    try
    {
        process.Start();
        process.BeginOutputReadLine();
        stdError = process.StandardError.ReadToEnd();
        process.WaitForExit();
    }
    catch (Exception e)
    {
        throw new Exception("OS error while executing " + Format(filename, arguments)+ ": " + e.Message, e);
    }

    if (process.ExitCode == 0)
    {
        return stdOutput.ToString();
    }
    else
    {
        var message = new StringBuilder();

        if (!string.IsNullOrEmpty(stdError))
        {
            message.AppendLine(stdError);
        }

        if (stdOutput.Length != 0)
        {
            message.AppendLine("Std output:");
            message.AppendLine(stdOutput.ToString());
        }

        throw new Exception(Format(filename, arguments) + " finished with exit code = " + process.ExitCode + ": " + message);
    }
}

private string Format(string filename, string arguments)
{
    return "'" + filename + 
        ((string.IsNullOrEmpty(arguments)) ? string.Empty : " " + arguments) +
        "'";
}
84
Lu55
 System.Diagnostics.ProcessStartInfo psi =
   new System.Diagnostics.ProcessStartInfo(@"program_to_call.exe");
 psi.RedirectStandardOutput = true;
 psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
 psi.UseShellExecute = false;
 System.Diagnostics.Process proc System.Diagnostics.Process.Start(psi);;
 System.IO.StreamReader myOutput = proc.StandardOutput;
 proc.WaitForExit(2000);
 if (proc.HasExited)
  {
  string output = myOutput.ReadToEnd();
 }
13
Jeff Mc

Přijatá odpověď na této stránce má slabost, která je ve vzácných situacích problematická. Existují dvě popisovače souborů, do kterých programy zapisují konvencí, stdout a stderr. Pokud jste právě přečetli jeden popisovač souboru, jako je odpověď od Raye, a program, který spouštíte, zapíše dostatek výstupu pro stderr, vyplní výstupní buffer stderr a blok. Pak jsou vaše dva procesy zablokovány. Velikost vyrovnávací paměti může být 4 kB. Toto je extrémně vzácné u krátkodobých programů, ale pokud máte dlouhodobě spuštěný program, který opakovaně vydává stderr, stane se to nakonec. To je obtížné ladit a sledovat.

Existuje několik dobrých způsobů, jak se s tím vypořádat.

  1. Jedním ze způsobů je spuštění programu cmd.exe místo vašeho programu a použití argumentu/c pro cmd.exe k vyvolání programu spolu s argumentem "2> & 1" pro program cmd.exe, který mu řekne, aby sloučil stdout a stderr.

            var p = new Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.Arguments = "/c mycmd.exe 2>&1";
    
  2. Dalším způsobem je použití programovacího modelu, který čte obě úchyty současně.

            var p = new Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.Arguments = @"/c dir \windows";
            p.StartInfo.CreateNoWindow = true;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.RedirectStandardInput = false;
            p.OutputDataReceived += (a, b) => Console.WriteLine(b.Data);
            p.ErrorDataReceived += (a, b) => Console.WriteLine(b.Data);
            p.Start();
            p.BeginErrorReadLine();
            p.BeginOutputReadLine();
            p.WaitForExit();
    
8
Cameron

Budete muset použít ProcessStartInfo s povoleným RedirectStandardOutput - pak si můžete přečíst výstupní tok. Možná bude pro vás snazší použít ">" k přesměrování výstupu do souboru (prostřednictvím OS) a pak soubor jednoduše přečíst.

[edit: jako to, co Ray udělal: +1]

6
Marc Gravell

Pokud vám nevadí zavedení závislosti, CliWrap vám to může zjednodušit:

var cli = new Cli("target.exe");
var output = await cli.ExecuteAsync("arguments", "stdin");
var stdout = output.StandardOutput;
4
Tyrrrz

To nemusí být nejlepší/nejjednodušší způsob, ale může to být možnost:

Při spuštění z kódu přidejte "> output.txt" a přečtěte si soubor output.txt.

3
Kon

Pomocí třídy Process můžete spustit libovolný program příkazového řádku a nastavit vlastnost StandardOutput instance Process pomocí čtečky streamů, kterou vytvoříte (buď na základě řetězce nebo umístění paměti). Po dokončení procesu můžete v tomto proudu provést cokoli, co potřebujete.

3
Nick

To může být užitečné pro někoho, pokud se pokoušíte dotazovat místní ARP cache na PC/Serveru.

List<string[]> results = new List<string[]>();

        using (Process p = new Process())
        {
            p.StartInfo.CreateNoWindow = true;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.Arguments = "/c arp -a";
            p.StartInfo.FileName = @"C:\Windows\System32\cmd.exe";
            p.Start();

            string line;

            while ((line = p.StandardOutput.ReadLine()) != null)
            {
                if (line != "" && !line.Contains("Interface") && !line.Contains("Physical Address"))
                {
                    var lineArr = line.Trim().Split(' ').Select(n => n).Where(n => !string.IsNullOrEmpty(n)).ToArray();
                    var arrResult = new string[]
                {
                   lineArr[0],
                   lineArr[1],
                   lineArr[2]
                };
                    results.Add(arrResult);
                }
            }

            p.WaitForExit();
        }
3
Kitson88

V PublicDomain otevřeném zdrojovém kódu je třída ProcessHelper, která by vás mohla zajímat.

2
Shaik

Jen pro zábavu, tady je moje dokončené řešení pro získání výstupu PYTHON - kliknutím na tlačítko - s hlášením chyb. Stačí přidat tlačítko s názvem "butPython" a štítek s názvem "llHello" ...

    private void butPython(object sender, EventArgs e)
    {
        llHello.Text = "Calling Python...";
        this.Refresh();
        Tuple<String,String> python = GoPython(@"C:\Users\BLAH\Desktop\Code\Python\BLAH.py");
        llHello.Text = python.Item1; // Show result.
        if (python.Item2.Length > 0) MessageBox.Show("Sorry, there was an error:" + Environment.NewLine + python.Item2);
    }

    public Tuple<String,String> GoPython(string pythonFile, string moreArgs = "")
    {
        ProcessStartInfo PSI = new ProcessStartInfo();
        PSI.FileName = "py.exe";
        PSI.Arguments = string.Format("\"{0}\" {1}", pythonFile, moreArgs);
        PSI.CreateNoWindow = true;
        PSI.UseShellExecute = false;
        PSI.RedirectStandardError = true;
        PSI.RedirectStandardOutput = true;
        using (Process process = Process.Start(PSI))
            using (StreamReader reader = process.StandardOutput)
            {
                string stderr = process.StandardError.ReadToEnd(); // Error(s)!!
                string result = reader.ReadToEnd(); // What we want.
                return new Tuple<String,String> (result,stderr); 
            }
    }
0
Dave