ฉันจะเรียกใช้แอปพลิเคชันคอนโซลจากแอปพลิเคชัน. NET และจับเอาต์พุตทั้งหมดที่สร้างในคอนโซลได้อย่างไร
(โปรดจำไว้ว่าฉันไม่ต้องการบันทึกข้อมูลไว้ในไฟล์ก่อนแล้วจึงวางใจเพราะฉันชอบที่จะรับข้อมูลเป็นแบบสด)
ฉันจะเรียกใช้แอปพลิเคชันคอนโซลจากแอปพลิเคชัน. NET และจับเอาต์พุตทั้งหมดที่สร้างในคอนโซลได้อย่างไร
(โปรดจำไว้ว่าฉันไม่ต้องการบันทึกข้อมูลไว้ในไฟล์ก่อนแล้วจึงวางใจเพราะฉันชอบที่จะรับข้อมูลเป็นแบบสด)
คำตอบ:
สิ่งนี้สามารถทำได้อย่างง่ายดายโดยใช้คุณสมบัติProcessStartInfo.RedirectStandardOutput ตัวอย่างฉบับสมบูรณ์มีอยู่ในเอกสาร MSDN ที่เชื่อมโยง ข้อแม้เดียวคือคุณอาจต้องเปลี่ยนเส้นทางสตรีมข้อผิดพลาดมาตรฐานด้วยเพื่อดูผลลัพธ์ทั้งหมดของแอปพลิเคชันของคุณ
Process compiler = new Process();
compiler.StartInfo.FileName = "csc.exe";
compiler.StartInfo.Arguments = "/r:System.dll /out:sample.exe stdstr.cs";
compiler.StartInfo.UseShellExecute = false;
compiler.StartInfo.RedirectStandardOutput = true;
compiler.Start();
Console.WriteLine(compiler.StandardOutput.ReadToEnd());
compiler.WaitForExit();
Console.Write
แทน
นี่คือการปรับปรุงบิตมากกว่าคำตอบที่ได้รับการยอมรับจาก@mdb นอกจากนี้เรายังตรวจจับผลลัพธ์ข้อผิดพลาดของกระบวนการ นอกจากนี้เราจับเอาท์พุทเหล่านี้ผ่านเหตุการณ์เนื่องจากReadToEnd()
ไม่ทำงานหากคุณต้องการจับทั้งข้อผิดพลาดและเอาต์พุตปกติ ฉันใช้เวลาพอสมควรในการทำงานนี้เพราะจริงๆแล้วต้องใช้การBeginxxxReadLine()
โทรหลังจากนั้นStart()
ด้วย
วิธีอะซิงโครนัส:
using System.Diagnostics;
Process process = new Process();
void LaunchProcess()
{
process.EnableRaisingEvents = true;
process.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(process_OutputDataReceived);
process.ErrorDataReceived += new System.Diagnostics.DataReceivedEventHandler(process_ErrorDataReceived);
process.Exited += new System.EventHandler(process_Exited);
process.StartInfo.FileName = "some.exe";
process.StartInfo.Arguments = "param1 param2";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
process.BeginErrorReadLine();
process.BeginOutputReadLine();
//below line is optional if we want a blocking call
//process.WaitForExit();
}
void process_Exited(object sender, EventArgs e)
{
Console.WriteLine(string.Format("process exited with code {0}\n", process.ExitCode.ToString()));
}
void process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine(e.Data + "\n");
}
void process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine(e.Data + "\n");
}
ใช้ProcessInfo.RedirectStandardOutputเพื่อเปลี่ยนทิศทางเอาต์พุตเมื่อสร้างกระบวนการคอนโซลของคุณ
จากนั้นคุณสามารถใช้Process.StandardOutputเพื่ออ่านผลลัพธ์ของโปรแกรม
ลิงค์ที่สองมีโค้ดตัวอย่างวิธีการทำ
ConsoleAppLauncherเป็นไลบรารีโอเพ่นซอร์สที่สร้างขึ้นเพื่อตอบคำถามนั้นโดยเฉพาะ จับเอาท์พุททั้งหมดที่สร้างขึ้นในคอนโซลและมีอินเทอร์เฟซที่เรียบง่ายเพื่อเริ่มและปิดแอปพลิเคชันคอนโซล
เหตุการณ์ ConsoleOutput จะเริ่มทำงานทุกครั้งเมื่อมีการเขียนบรรทัดใหม่โดยคอนโซลไปยังเอาต์พุตมาตรฐาน / ข้อผิดพลาด บรรทัดจะอยู่ในคิวและรับประกันว่าจะเป็นไปตามลำดับเอาต์พุต
นอกจากนี้ยังมีแพคเกจ NuGet
ตัวอย่างการโทรเพื่อรับเอาต์พุตคอนโซลแบบเต็ม:
// Run simplest shell command and return its output.
public static string GetWindowsVersion()
{
return ConsoleApp.Run("cmd", "/c ver").Output.Trim();
}
ตัวอย่างพร้อมข้อเสนอแนะสด:
// Run ping.exe asynchronously and return roundtrip times back to the caller in a callback
public static void PingUrl(string url, Action<string> replyHandler)
{
var regex = new Regex("(time=|Average = )(?<time>.*?ms)", RegexOptions.Compiled);
var app = new ConsoleApp("ping", url);
app.ConsoleOutput += (o, args) =>
{
var match = regex.Match(args.Line);
if (match.Success)
{
var roundtripTime = match.Groups["time"].Value;
replyHandler(roundtripTime);
}
};
app.Run();
}
ฉันได้เพิ่มวิธีการช่วยเหลือหลายวิธีในแพลตฟอร์ม O2 (โครงการโอเพ่นซอร์ส) ซึ่งช่วยให้คุณสามารถเขียนสคริปต์การโต้ตอบกับกระบวนการอื่นได้อย่างง่ายดายผ่านเอาต์พุตและอินพุตของคอนโซล (ดูhttp://code.google.com/p/o2platform/ ซอร์ส / เรียกดู / trunk / O2_Scripts / APIs / Windows / CmdExe / CmdExeAPI.cs )
นอกจากนี้ยังมีประโยชน์สำหรับคุณอาจเป็น API ที่ช่วยให้สามารถดูเอาต์พุตคอนโซลของกระบวนการปัจจุบัน (ในตัวควบคุมหรือหน้าต่างป๊อปอัปที่มีอยู่) ดูรายละเอียดเพิ่มเติมในบล็อกโพสต์นี้: http://o2platform.wordpress.com/2011/11/26/api_consoleout-cs-inprocess-capture-of-the-console-output/ (บล็อกนี้ยังมีรายละเอียดวิธีการบริโภค เอาต์พุตคอนโซลของกระบวนการใหม่)
ฉันสร้างเวอร์ชันรีแอคทีฟที่ยอมรับการเรียกกลับสำหรับ stdOut และ StdErr
onStdOut
และonStdErr
เรียกว่าแบบอะซิงโครนัส
ทันทีที่ข้อมูลมาถึง (ก่อนที่กระบวนการจะออก)
public static Int32 RunProcess(String path,
String args,
Action<String> onStdOut = null,
Action<String> onStdErr = null)
{
var readStdOut = onStdOut != null;
var readStdErr = onStdErr != null;
var process = new Process
{
StartInfo =
{
FileName = path,
Arguments = args,
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = readStdOut,
RedirectStandardError = readStdErr,
}
};
process.Start();
if (readStdOut) Task.Run(() => ReadStream(process.StandardOutput, onStdOut));
if (readStdErr) Task.Run(() => ReadStream(process.StandardError, onStdErr));
process.WaitForExit();
return process.ExitCode;
}
private static void ReadStream(TextReader textReader, Action<String> callback)
{
while (true)
{
var line = textReader.ReadLine();
if (line == null)
break;
callback(line);
}
}
สิ่งต่อไปนี้จะทำงานexecutable
พร้อมกับargs
พิมพ์
ไปที่คอนโซล
RunProcess(
executable,
args,
s => { Console.ForegroundColor = ConsoleColor.White; Console.WriteLine(s); },
s => { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(s); }
);
จากPythonTR - Python ProgramcılarıDerneği, e-kitap, örnek :
Process p = new Process(); // Create new object
p.StartInfo.UseShellExecute = false; // Do not use shell
p.StartInfo.RedirectStandardOutput = true; // Redirect output
p.StartInfo.FileName = "c:\\python26\\python.exe"; // Path of our Python compiler
p.StartInfo.Arguments = "c:\\python26\\Hello_C_Python.py"; // Path of the .py to be executed
เพิ่มprocess.StartInfo.**CreateNoWindow** = true;
และtimeout
.
private static void CaptureConsoleAppOutput(string exeName, string arguments, int timeoutMilliseconds, out int exitCode, out string output)
{
using (Process process = new Process())
{
process.StartInfo.FileName = exeName;
process.StartInfo.Arguments = arguments;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.CreateNoWindow = true;
process.Start();
output = process.StandardOutput.ReadToEnd();
bool exited = process.WaitForExit(timeoutMilliseconds);
if (exited)
{
exitCode = process.ExitCode;
}
else
{
exitCode = -1;
}
}
}
StandardOutput.ReadToEnd()
มันจะไม่กลับไปที่คำสั่งถัดไปจนกว่าจะสิ้นสุดแอพ ดังนั้นการหมดเวลาของคุณใน WaitForExit (timeoutMilliseconds) จึงไม่ทำงาน! (รหัสของคุณจะค้าง!)