ฉันต้องการเรียกใช้โปรแกรมบรรทัดคำสั่งภายนอกจากแอพ Mono / .NET ของฉัน ตัวอย่างเช่นผมต้องการเรียกmencoder เป็นไปได้ไหม:
- เพื่อรับเอาต์พุตเชลล์บรรทัดคำสั่งและเขียนลงในกล่องข้อความของฉัน?
- วิธีรับค่าตัวเลขเพื่อแสดงแถบความคืบหน้าเมื่อเวลาผ่านไป?
ฉันต้องการเรียกใช้โปรแกรมบรรทัดคำสั่งภายนอกจากแอพ Mono / .NET ของฉัน ตัวอย่างเช่นผมต้องการเรียกmencoder เป็นไปได้ไหม:
คำตอบ:
เมื่อคุณสร้างProcess
ชุดวัตถุของคุณStartInfo
อย่างเหมาะสม:
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "program.exe",
Arguments = "command line arguments to your executable",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
จากนั้นเริ่มต้นกระบวนการและอ่านจากมัน:
proc.Start();
while (!proc.StandardOutput.EndOfStream)
{
string line = proc.StandardOutput.ReadLine();
// do something with line
}
คุณสามารถใช้int.Parse()
หรือint.TryParse()
เพื่อแปลงสตริงเป็นค่าตัวเลข คุณอาจต้องทำการจัดการสตริงก่อนถ้ามีตัวเลขที่ไม่ถูกต้องในสตริงที่คุณอ่าน
คุณสามารถดำเนินการส่งออกของคุณพร้อมหรือไม่พร้อม
1. ตัวอย่างซิงโครนัส
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();
}
โปรดทราบว่าการประมวลผลเอาต์พุตและข้อผิดพลาดดีกว่า: ต้องจัดการแยกต่างหาก
(*) สำหรับบางคำสั่ง (ที่นี่StartInfo.Arguments
) คุณต้องเพิ่ม/c
คำสั่งWaitForExit()
มิฉะนั้นค้างกระบวนการใน
2. ตัวอย่างแบบอะซิงโครนัส
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);
}
หากคุณไม่จำเป็นต้องทำการดำเนินการที่ซับซ้อนด้วยเอาต์พุตคุณสามารถข้ามเมธอด OutputHandler เพียงเพิ่มตัวจัดการอินไลน์โดยตรง:
//* Set your output and error (asynchronous) handlers
process.OutputDataReceived += (s, e) => Console.WriteLine(e.Data);
process.ErrorDataReceived += (s, e) => Console.WriteLine(e.Data);
เอาล่ะสำหรับผู้ที่ต้องการอ่านข้อผิดพลาดและผลลัพธ์ แต่ได้รับการหยุดชะงักด้วยวิธีการแก้ปัญหาใด ๆ ที่ให้ไว้ในคำตอบอื่น ๆ (เช่นฉัน) ที่นี่เป็นวิธีการแก้ปัญหาที่ฉันสร้างขึ้นหลังจากอ่านคำอธิบาย MSDN สำหรับStandardOutput
ทรัพย์สิน
คำตอบขึ้นอยู่กับรหัสของ 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(ErrorOutputHandler);
//* 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 ErrorOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
//* Do your stuff with the output (write to console/log/StringBuilder)
Console.WriteLine(outLine.Data);
}
วิธีการ. NET มาตรฐานในการทำเช่นนี้คือการอ่านจากสตรีมกระบวนการ ' StandardOutput มีตัวอย่างในเอกสาร MSDN ที่เชื่อมโยง ที่คล้ายกันคุณสามารถอ่านได้จากStandardErrorและเขียนไปStandardInput
เป็นไปได้ที่จะรับเอาต์พุตเชลล์บรรทัดคำสั่งของกระบวนการตามที่อธิบายไว้ที่นี่: http://www.c-sharpcorner.com/UploadFile/edwinlima/SystemDiagnosticProcess12052005035444AM/SystemDiagnosticProcess.aspx
ขึ้นอยู่กับ mencoder ถ้าเป็นสถานะนี้ในบรรทัดคำสั่งใช่แล้ว :)
คุณสามารถใช้หน่วยความจำที่ใช้ร่วมกันสำหรับ 2 กระบวนการในการสื่อสารผ่านตรวจสอบ MemoryMappedFile
คุณส่วนใหญ่จะสร้างไฟล์หน่วยความจำที่แมปmmf
ในกระบวนการหลักโดยใช้คำสั่ง "ใช้" แล้วสร้างกระบวนการที่สองจนกว่ามันจะยุติและปล่อยให้มันเขียนผลการmmf
ใช้BinaryWriter
แล้วอ่านผลจากการmmf
ใช้กระบวนการแม่คุณยังสามารถ ส่งmmf
ชื่อโดยใช้อาร์กิวเมนต์บรรทัดคำสั่งหรือรหัสยาก
ตรวจสอบให้แน่ใจเมื่อใช้ไฟล์ที่แม็พในกระบวนการพาเรนต์ที่คุณทำให้กระบวนการลูกเขียนผลลัพธ์ไปยังไฟล์ที่แม็พก่อนที่ไฟล์แม็พจะถูกปล่อยในกระบวนการพาเรนต์
ตัวอย่าง: กระบวนการหลัก
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();
}
กระบวนการลูก
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();
}
ในการใช้ตัวอย่างนี้คุณจะต้องสร้างโซลูชันที่มี 2 โครงการภายในจากนั้นคุณจะสร้างผลลัพธ์ของกระบวนการลูกจาก% childDir% / bin / debug และคัดลอกไปยัง% parentDirectory% / bin / debug จากนั้นเรียกใช้ โครงการหลัก
childDir
และparentDirectory
เป็นชื่อโฟลเดอร์ของโครงการของคุณในพีซีโชคดี :)
วิธีเรียกใช้โปรเซส (เช่นไฟล์ bat, perl script, โปรแกรมคอนโซล) และแสดงเอาต์พุตมาตรฐานในรูปแบบ windows:
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();
คุณสามารถค้นหาได้ProcessCaller
ที่ลิงค์นี้: การเปิดตัวกระบวนการและการแสดงผลมาตรฐานของมัน
คุณสามารถบันทึกผลลัพธ์ของกระบวนการโดยใช้รหัสด้านล่าง:
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) {
}
ทางออกที่ได้ผลสำหรับฉันในการชนะและ linux คือ folling
// 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 };
}
}