मैं C # से कमांड-लाइन प्रोग्राम को कैसे निष्पादित करूं और STD OUT परिणाम प्राप्त करूं? विशेष रूप से, मैं दो फ़ाइलों पर डीआईएफएफ निष्पादित करना चाहता हूं जो प्रोग्रामेटिक रूप से चयनित हैं और एक टेक्स्ट बॉक्स में परिणाम लिखते हैं।
मैं C # से कमांड-लाइन प्रोग्राम को कैसे निष्पादित करूं और STD OUT परिणाम प्राप्त करूं? विशेष रूप से, मैं दो फ़ाइलों पर डीआईएफएफ निष्पादित करना चाहता हूं जो प्रोग्रामेटिक रूप से चयनित हैं और एक टेक्स्ट बॉक्स में परिणाम लिखते हैं।
जवाबों:
// 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();
कोड MSDN से है ।
{YourProcessObject}.StartInfo.Arguments
स्ट्रिंग के माध्यम से अपने कॉल में तर्क जोड़ सकते हैं ।
p.StandardError
स्ट्रीम को पर्याप्त डेटा लिखा है। जब धारा पूर्ण हो जाती है, तो ऐसा प्रतीत होता है कि डेटा का उपभोग होने तक यह प्रक्रिया रुक जाएगी, इसलिए मुझे दोनों को पढ़ना होगा StandardError
और StandardOutput
यह सुनिश्चित करने के लिए कि कोई कार्य सही तरीके से निष्पादित होता है।
यहाँ एक त्वरित नमूना है:
//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();
वहां एक अन्य पैरामीटर मुझे उपयोगी लगा, जिसका उपयोग मैं प्रक्रिया विंडो को खत्म करने के लिए करता हूं
pProcess.StartInfo.CreateNoWindow = true;
यह ब्लैक कंसोल विंडो को उपयोगकर्ता से पूरी तरह से छिपाने में मदद करता है, यदि आपकी यही इच्छा है।
// 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) +
"'";
}
process.StartInfo.RedirectStandardError = true;
और if (process.ExitCode == 0)
जो स्वीकृत उत्तर नहीं है।
इस पृष्ठ पर स्वीकृत उत्तर में एक कमजोरी है जो दुर्लभ स्थितियों में परेशानी है। दो फाइल हैंडल हैं, जो प्रोग्राम कन्वेंशन, स्टडआउट और स्टडर द्वारा लिखते हैं। यदि आप सिर्फ रे से जवाब के रूप में एक एकल फ़ाइल हैंडल पढ़ते हैं, और जिस प्रोग्राम को आप शुरू कर रहे हैं, वह stderr को पर्याप्त आउटपुट लिखता है, यह आउटपुट stderr बफर और ब्लॉक को भर देगा। फिर आपकी दो प्रक्रियाएं गतिरोध हैं। बफर का आकार 4K हो सकता है। यह अल्पकालिक कार्यक्रमों पर अत्यंत दुर्लभ है, लेकिन अगर आपके पास एक लंबा चलने वाला कार्यक्रम है जो बार-बार स्टडर के लिए आउटपुट करता है, तो यह अंततः होगा। यह डिबग और ट्रैक करने के लिए मुश्किल है।
इससे निपटने के लिए कुछ अच्छे तरीके हैं।
एक तरीका यह है कि अपने प्रोग्राम के बजाय cmd.exe को निष्पादित करें और cmd.exe के साथ / c तर्क का उपयोग करके अपने प्रोग्राम को "2> और 1" तर्क के साथ cmd.exe में इसे stdout और stderr को मर्ज करने के लिए कहें।
var p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c mycmd.exe 2>&1";
एक अन्य तरीका एक प्रोग्रामिंग मॉडल का उपयोग करना है जो एक ही समय में दोनों हैंडल पढ़ता है।
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();
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();
}
आपको सक्षम के ProcessStartInfo
साथ उपयोग करने की आवश्यकता होगी RedirectStandardOutput
- फिर आप आउटपुट स्ट्रीम पढ़ सकते हैं। आपको फ़ाइल में (OS के माध्यम से) आउटपुट को रीडायरेक्ट करने के लिए ">" का उपयोग करना आसान हो सकता है, और फिर बस फ़ाइल को पढ़ें।
[संपादित करें: जैसे रे ने क्या किया: +1]
RedirectStandardOutput
वास्तव में उपयोग करने में आसान ।
आप प्रोसेस क्लास का उपयोग करके किसी भी कमांड लाइन प्रोग्राम को लॉन्च कर सकते हैं, और आपके द्वारा बनाए जाने वाले स्ट्रीम रीडर के साथ प्रक्रिया उदाहरण की StandardOutput संपत्ति सेट कर सकते हैं (या तो एक स्ट्रिंग या मेमोरी लोकेशन पर आधारित)। प्रक्रिया पूरी होने के बाद, आप उस स्ट्रीम पर जो कुछ भी आवश्यक है, उसे कर सकते हैं।
यह किसी के लिए उपयोगी हो सकता है यदि आपका पीसी / सर्वर पर स्थानीय एआरपी कैश को क्वेरी करने का प्रयास कर रहा है।
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();
}
वन-लाइनर रन कमांड:
new Process() { StartInfo = new ProcessStartInfo("echo", "Hello, World") }.Start();
कम कोड की कम मात्रा में कमांड का आउटपुट पढ़ें:
var cliProcess = new Process() {
StartInfo = new ProcessStartInfo("echo", "Hello, World") {
UseShellExecute = false,
RedirectStandardOutput = true
}
};
cliProcess.Start();
string cliOut = cliProcess.StandardOutput.ReadToEnd();
cliProcess.WaitForExit();
cliProcess.Close();
PublicDomain के ओपन सोर्स कोड में एक ProcessHelper Class है, जिसमें आपकी रुचि हो सकती है।
यदि आपको cmd.exe में कुछ कमांड निष्पादित करने की आवश्यकता होती है, तो आप निम्नलिखित कार्य कर सकते हैं:
// 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 = "cmd.exe";
p.StartInfo.Arguments = "/C vol";
p.Start();
// Read the output stream first and then wait.
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Console.WriteLine(output);
यह केवल कमांड का आउटपुट देता है:
आप StandardInput
इसके स्थान पर उपयोग कर सकते हैं StartInfo.Arguments
:
// Start the child process.
Process p = new Process();
// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "cmd.exe";
p.Start();
// Read the output stream first and then wait.
p.StandardInput.WriteLine("vol");
p.StandardInput.WriteLine("exit");
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Console.WriteLine(output);
परिणाम इस तरह दिखता है:
बस मज़े के लिए, यहाँ PYTHON आउटपुट प्राप्त करने के लिए मेरा पूरा समाधान है - एक बटन क्लिक के तहत - त्रुटि रिपोर्टिंग के साथ। बस "butPython" नामक बटन और "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);
}
}
चूँकि यहाँ अधिकांश उत्तर के लिए using
स्टेटमेन्ट लागू नहीं किया गया है IDisposable
और कुछ अन्य सामान जो मुझे लगता है कि यह उत्तर हो सकता है, मैं इसे उत्तर जोड़ूंगा ।
C # 8.0 के लिए
// Start a process with the filename or path with filename e.g. "cmd". Please note the
//using statemant
using myProcess.StartInfo.FileName = "cmd";
// add the arguments - Note add "/c" if you want to carry out tge argument in cmd and
// terminate
myProcess.StartInfo.Arguments = "/c dir";
// Allows to raise events
myProcess.EnableRaisingEvents = true;
//hosted by the application itself to not open a black cmd window
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.CreateNoWindow = true;
// Eventhander for data
myProcess.Exited += OnOutputDataRecived;
// Eventhandler for error
myProcess.ErrorDataReceived += OnErrorDataReceived;
// Eventhandler wich fires when exited
myProcess.Exited += OnExited;
// Starts the process
myProcess.Start();
//read the output before you wait for exit
myProcess.BeginOutputReadLine();
// wait for the finish - this will block (leave this out if you dont want to wait for
// it, so it runs without blocking)
process.WaitForExit();
// Handle the dataevent
private void OnOutputDataRecived(object sender, DataReceivedEventArgs e)
{
//do something with your data
Trace.WriteLine(e.Data);
}
//Handle the error
private void OnErrorDataReceived(object sender, DataReceivedEventArgs e)
{
Trace.WriteLine(e.Data);
//do something with your exception
throw new Exception();
}
// Handle Exited event and display process information.
private void OnExited(object sender, System.EventArgs e)
{
Trace.WriteLine("Process exited");
}