How to compile Java from C#? - c#

I'm trying to use the following C# code to compile Java using javac:
Process p = new Process();
p.StartInfo.FileName = "javac";
Directory.CreateDirectory(Application.StartupPath + #"/TempJava");
p.StartInfo.Arguments = "-d "Application.StartupPath + #"/TempJava" + files;
p.Start();
"files" represents a string variable containing the name(s) of the *.java files.
All in all, I want to create a new folder, and then take the Java files (from where ever they may be located) and compile it into a class file(s) in TempJava.
For some reason, the code doesn't work, no errors, no warnings, but when I run it and check TempJava, there's no files in it.

Just because your child process ends with a possible error, it doesn't mean your parent process must be aware of it.
Inspect the process' exit code and standard output stream, and especially the standard error stream. Your answer lies in there...

here i have 2 buttons run and compile here is some code to help.
private void comp_Click(object sender, EventArgs e)
{
string text = "javac " + label1.Text + file + "#pause" + "#stop";
text = text.Replace("#", System.Environment.NewLine);
File.WriteAllText(label1.Text + "Compile.bat", text);
Process proc = null;
try
{
proc = new Process();
proc.StartInfo.FileName = label1.Text + "Compile.bat";
proc.StartInfo.CreateNoWindow = false;
proc.Start();
proc.WaitForExit();
}
catch
{
}
}
private void runp_Click(object sender, EventArgs e)
{
string news = file.Remove(file.Length - 5);
string text = "java " + news + "#pause";
text = text.Replace("#", System.Environment.NewLine);
File.WriteAllText(label1.Text + "Run.bat", text);
Process proc = null;
try
{
proc = new Process();
proc.StartInfo.FileName = label1.Text + "Run.bat";
proc.StartInfo.WorkingDirectory = label1.Text.Remove(label1.Text.Length - 1);
proc.StartInfo.CreateNoWindow = true;
proc.Start();
proc.WaitForExit();
}
catch
{
}
}
all i really do is create a batch and run it using c#.

Related

Process.Start() is not releasing file handles

I have some code that is creating a PNG file of a graph of Nodes using GraphViz's dot program. This first time through the code works perfectly. However, if I try to run the method again it fails because the file is still considered in use by windows.
Here is the relevant code to start the dot.exe process:
private void MakePng()
{
string args = "-o" + graphPath + " -Tpng " + dotPath;
Process process = new Process();
ProcessStartInfo info = new ProcessStartInfo();
info.FileName = VizGraphPath;
info.Arguments = args;
info.UseShellExecute = false;
info.CreateNoWindow = true;
process.StartInfo = info;
process.EnableRaisingEvents = true;
process.Exited += new EventHandler(Process_Exited);
process.Start();
}
private void Process_Exited(object sender, EventArgs e)
{
UpdateCanvas();
}
The various string variables named xxxPath are just static strings to the correct file paths. When the program starts up and I run this code everything works perfectly. But if I reset my graph and try to run this set of code again it fails to create a new PNG. The old one is still there. To test something out I added this line:
private void MakePng()
{
string args = "-o" + graphPath + " -Tpng " + dotPath;
File.Delete(graphPath);
Which works the first time through. But the second time it throws a Exception stating File is still in use. So I'm guessing somehow when the Process I start exits, the File Handle it created is still in use even though it exited? Any suggestions about how to figure out why its still in use or how to fix it?
My UpdateCanvas function is also accessing the file that is locked:
public void UpdateCanvas()
{
Bitmap image = new Bitmap(graphPath);
pbCanvas.Image = image;
}
Do i need to something when loading a bitmap from a file to release the file?
It was indeed the Bitmap locking the file. I had to dispose of it before the file would be unlocked.
Your file is locked by new Bitmap.
Rewrite it with:
public void UpdateCanvas()
{
Image img;
using (var bmpTemp = new Bitmap(graphPath))
{
img = new Bitmap(bmpTemp);
}
pbCanvas.Image = img;
}
Process class implements IDisposable, so you need to despose resources. Also, you can add WatForExit method to be sure, your process finished:
private void MakePng()
{
string args = "-o" + graphPath + " -Tpng " + dotPath;
using(Process process = new Process())
{
ProcessStartInfo info = new ProcessStartInfo();
info.FileName = VizGraphPath;
info.Arguments = args;
info.UseShellExecute = false;
info.CreateNoWindow = true;
process.StartInfo = info;
process.EnableRaisingEvents = true;
process.Start();
process.WaitForExit(10*1000); //10 seconds
}
UpdateCanvas();
}

Aylien Sentiment Analysis using Console application

I'm facing a problem. I am using Aylien API for sentiment analysis. When i run this code, i will get a value of neutral 0.99823.
static void Main(string[] args)
{
Client client = new Client("ID", "Key");
string filename = "tweet.txt"; // Declare the file name
string inputString = System.IO.File.ReadAllText(filename); // Read all text in File to String.
Sentiment sentiment = client.Sentiment(text: inputString);
Console.WriteLine("The Tweets are : " + sentiment.Polarity + " " + sentiment.PolarityConfidence);
Console.WriteLine(sentiment.Subjectivity + " " + sentiment.SubjectivityConfidence+"\n");
Console.WriteLine("Press ENTER to close...");
Console.ReadLine();
}
However when i run my second code to invoke the method from another console application, it always display positive 1. Do anyone know why?
var proc = Process.Start(#"C:\\ConsoleApplication1");
proc.WaitForExit();
var exitCode = proc.ExitCode;
You're getting the exit code from the process, which generally indicates success/failure, 0 generally means the process ended successfully, anything else generally means something went wrong, although the creator of your app could be returning anything they want.
If you want to get the output from the actual application you should read the standard output from process by doing the following:
var proc = new Process();
proc.StartInfo.FileName = #"C:\\ConsoleApplication1";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.OutputDataReceived += Proc_OutputDataReceived;
proc.Start();
proc.BeginOutputReadLine();
proc.WaitForExit();
private static void Proc_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine(e.Data);
}

How do I allow a c# process to create a file as if it were run on the command line?

I am trying to execute a process exactly as if it were executed on the window's command line but the process class won't allow the executable to create a file similar to what it would do if it were run from the command line. The Processes will when deployed run asynchronously on a server at timed intervals. The command line would calls would look like this:
curl.exe url -o data
wgrib2.exe data -csv output.csv
In the code below I found a workaround for curl.exe but when it is read as StandardOutput the file cuts off some of the critical stopping characters for this file type.
public static void httpQuery(string queryString)
{
Process myProcess = new Process();
try
{
string basepath = AppDomain.CurrentDomain.BaseDirectory;
myProcess.StartInfo.UseShellExecute = false; // allows us to redirect the output
myProcess.StartInfo.CreateNoWindow = true; // stop's command window from being made
myProcess.StartInfo.Verb = "runas";
myProcess.StartInfo.FileName = #"C:\Users\Ian's\Desktop\wgrib2\curl.exe";
myProcess.StartInfo.Arguments = queryString; // queryString is http://nomads.noaa.gov/....
myProcess.StartInfo.RedirectStandardError = true; // redirect error to stream reader
myProcess.StartInfo.RedirectStandardOutput = true; // redirect output to strem reader
myProcess.Start();
if (myProcess.WaitForExit(10000) == false)
{
myProcess.Kill();
}
using(StreamReader reader = myProcess.StandardError) // capture error output if any
{
string result = reader.ReadToEnd();
reader.Close();
StreamReader message = myProcess.StandardOutput;
string output = message.ReadToEnd();
StreamWriter writer = new StreamWriter(basepath + "wgrib2\\data");
writer.Write(output);
writer.Close();
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
myProcess.Close();
}
Additionally, I cannot seem to find a way to allow the second process to write a new file, or if it has been I cannot find the directory that it is writing to. I am working with VS2012 on the IIS development server. This is the second processes code.
public static void callWgrib2()
{
Process wgrib2 = new Process();
try
{
// call on command line: wgrib2.exe data -csv data.csv
string basepath = AppDomain.CurrentDomain.BaseDirectory; // path to project directory
string arg1 = basepath + "wgrib2\\data"; // filename of operate on
string arg2 =" -csv " + basepath + "wgrib2\\data.csv"; // filename to write to
wgrib2.StartInfo.UseShellExecute = false; // parameters
wgrib2.StartInfo.CreateNoWindow = true;
wgrib2.StartInfo.Verb = "runas";
wgrib2.StartInfo.FileName = #"C:\Users\Ian's\Desktop\wgrib2\wgrib2.exe";
wgrib2.StartInfo.Arguments = "\""+ arg1 + arg2 + "\"";
wgrib2.StartInfo.RedirectStandardError = true;
wgrib2.Start();
if (wgrib2.WaitForExit(10000) == false)
{
wgrib2.Kill();
}
using (StreamReader reader = wgrib2.StandardOutput)
{
string result = reader.ReadToEnd();
reader.Close();
StreamReader err = wgrib2.StandardError;
err.ReadToEnd();
err.Close();
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
wgrib2.Close();
}
Can someone point me in the write direction I have put considerable effort into this problem but I'm sure there exits a simple workaround I'm not aware of.
If you want to use the actual command line process, you can use cmd and pass the /c flag to it in the arguements
also, the line
wgrib2.StartInfo.Arguments = "\""+ arg1 + arg2 + "\"";
looks odd
do you really need all your arguments such as -csv to be in the same quotes block?
it's like calling on the command line
C:\Users\Ian's\Desktop\wgrib2\wgrib2.exe "c:\base\wgrib2\data -csv c:\base\wgrib2\data.csv"

I am trying to read the output of a process in c# but I get this message "Cannot mix synchronous and asynchronous operation on process stream."

I am writing a backup program using xcopy and because there are a lot of large files it takes a while so I want to show the progress. When I try to use StreamReader to get the standard output, it has this error message when I debug. "Cannot mix synchronous and asynchronous operation on process stream."
public void backup_worker_DoWork(object sender, DoWorkEventArgs e)
{
int loop = 1;
backup_worker.WorkerReportsProgress = true;
Process xcopy = new Process();
ProcessStartInfo startinfo = new ProcessStartInfo();
startinfo.CreateNoWindow = true;
startinfo.UseShellExecute = false;
startinfo.RedirectStandardError = true;
startinfo.RedirectStandardOutput = true;
startinfo.FileName = Environment.CurrentDirectory + "\\xcopy.exe";
startinfo.Arguments = '"' + source + '"' + " " + '"' + target + '"' + " " + "/s /e /y";
xcopy.StartInfo.RedirectStandardOutput = true;
xcopy.StartInfo = startinfo;
xcopy.Start();
xcopy.BeginErrorReadLine();
xcopy.BeginOutputReadLine();
StreamReader sr = xcopy.StandardOutput;
while (loop > 0)
{
progress = sr.ReadLine();
output_list.Items.Add(progress);
}
xcopy.OutputDataReceived += new DataReceivedEventHandler(backup_worker_OutputDataRecieved);
xcopy.ErrorDataReceived += new DataReceivedEventHandler(backup_worker_ErrorDataReceived);
xcopy.WaitForExit();
backup_worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backup_worker_RunWorkerCompleted);
}
void backup_worker_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
}
void backup_worker_OutputDataRecieved(object sender, DataReceivedEventArgs e)
{
}
void backup_worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Completed");
}
Please help.
Thanks in advance
The problem is that you're using both synchronous and asynchronous output:
// Using async version here...
xcopy.BeginOutputReadLine();
StreamReader sr = xcopy.StandardOutput;
while (loop > 0)
{
// Trying to use synchronous reading here
progress = sr.ReadLine();
You need to design your algorithm to use one option or the other, but not both.
The below note from MSDN should make it very clear, what the problem is
You cannot mix asynchronous and synchronous read operations on a redirected stream. Once the redirected stream of a Process is opened in either asynchronous or synchronous mode, all further read operations on that stream must be in the same mode. For example, do not follow BeginErrorReadLine with a call to ReadLine on the StandardError stream, or vice versa. However, you can read two different streams in different modes. For example, you can call BeginErrorReadLine and then call ReadLine for the StandardOutput stream.
Your code should be more on the lines as below
public void backup_worker_DoWork(object sender, DoWorkEventArgs e) {
int loop = 1;
// This should ideally not be in the DoWork, but where you setup or create the worker
backup_worker.WorkerReportsProgress = true;
backup_worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backup_worker_RunWorkerCompleted);
backup_worker.WorkerSupportsCancellation = true;
// setup your scopy process
ProcessStartInfo startinfo = new ProcessStartInfo();
startinfo.CreateNoWindow = true;
startinfo.UseShellExecute = false;
startinfo.RedirectStandardError = true;
startinfo.RedirectStandardOutput = true;
startinfo.FileName = Environment.CurrentDirectory + "\\xcopy.exe";
startinfo.Arguments = "/s /e /y " + '"' + source + '"' + " " + '"' + target + '"' + " ";
Process xcopy = new Process();
xcopy.StartInfo = startinfo;
xcopy.ErrorDataReceived += new DataReceivedEventHandler(backup_worker_ErrorDataReceived);
// start the xcopy and read the output
xcopy.Start();
xcopy.BeginErrorReadLine();
string copiedFileName;
while ((copiedFileName = xcopy.StandardOutput.ReadLine()) != null) {
output_list.Items.Add(copiedFileName);
}
// we should be done when here, but doesen't hurt to wait
xcopy.WaitForExit();
}
void backup_worker_ErrorDataReceived(object sender, DataReceivedEventArgs e) {
MessageBox.Show("We have a problem. Figure what needs to be done here!");
}
void backup_worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled == true) {
MessageBox.Show("Canceled!");
} else if (e.Error != null) {
MessageBox.Show("Error: " + e.Error.Message);
} else {
MessageBox.Show("Completed!");
}
}
If you want to do the synchronous way,
instead of
xcopy.BeginOutputReadLine()
use
string s = xcopy.StandardOutput.ReadToEnd()
be warned, that if you do that for both the output and the error, and one of them is too long, you can hit a deadlock.

How To: Execute command line in C#, get STD OUT results

How do I execute a command-line program from C# and get back the STD OUT results? Specifically, I want to execute DIFF on two files that are programmatically selected and write the results to a text box.
// 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();
Code is from MSDN.
Here's a quick sample:
//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();
There one other parameter I found useful, which I use to eliminate the process window
pProcess.StartInfo.CreateNoWindow = true;
this helps to hide the black console window from user completely, if that is what you desire.
// 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) +
"'";
}
The accepted answer on this page has a weakness that is troublesome in rare situations. There are two file handles which programs write to by convention, stdout, and stderr.
If you just read a single file handle such as the answer from Ray, and the program you are starting writes enough output to stderr, it will fill up the output stderr buffer and block. Then your two processes are deadlocked. The buffer size may be 4K.
This is extremely rare on short-lived programs, but if you have a long running program which repeatedly outputs to stderr, it will happen eventually. This is tricky to debug and track down.
There are a couple good ways to deal with this.
One way is to execute cmd.exe instead of your program and use the /c argument to cmd.exe to invoke your program along with the "2>&1" argument to cmd.exe to tell it to merge stdout and stderr.
var p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c mycmd.exe 2>&1";
Another way is to use a programming model which reads both handles at the same time.
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();
}
You will need to use ProcessStartInfo with RedirectStandardOutput enabled - then you can read the output stream. You might find it easier to use ">" to redirect the output to a file (via the OS), and then simply read the file.
[edit: like what Ray did: +1]
One-liner run command:
new Process() { StartInfo = new ProcessStartInfo("echo", "Hello, World") }.Start();
Read output of command in shortest amount of reable code:
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();
In case you also need to execute some command in the cmd.exe, you can do the following:
// 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);
This returns just the output of the command itself:
You can also use StandardInput instead of 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);
The result looks like this:
Since the most answers here dont implement the using statemant for IDisposable and some other stuff wich I think could be nessecary I will add this answer.
For 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");
}
Here is small example:
using System;
using System.Diagnostics;
class Program
{
static void Main(string[] args)
{
var p = Process.Start(
new ProcessStartInfo("git", "branch --show-current")
{
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true,
WorkingDirectory = Environment.CurrentDirectory
}
);
p.WaitForExit();
string branchName =p.StandardOutput.ReadToEnd().TrimEnd();
string errorInfoIfAny =p.StandardError.ReadToEnd().TrimEnd();
if (errorInfoIfAny.Length != 0)
{
Console.WriteLine($"error: {errorInfoIfAny}");
}
else {
Console.WriteLine($"branch: {branchName}");
}
}
}
I believe this is shortest form.
Please notice that most of command line tools easily confuse standard output and standard error, sometimes it makes sense just to clue those together into single string.
Also p.ExitCode might be sometimes useful.
Example above serves for purpose of writing command line utility like tools if you want to do it by yourself. Please note that for cli automation it's also possible to use Cake Frosten and Cake Git extension.
You can launch any command line program using the Process class, and set the StandardOutput property of the Process instance with a stream reader you create (either based on a string or a memory location). After the process completes, you can then do whatever diff you need to on that stream.
This might be useful for someone if your attempting to query the local ARP cache on a PC/Server.
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();
}
This may not be the best/easiest way, but may be an option:
When you execute from your code, add " > output.txt" and then read in the output.txt file.
There is a ProcessHelper Class in PublicDomain open source code which might interest you.
Julian's solution is tested working with some minor corrections. The following is an example that also used https://sourceforge.net/projects/bat-to-exe/ GenericConsole.cs and https://www.codeproject.com/Articles/19225/Bat-file-compiler program.txt for args part:
using System;
using System.Text; //StringBuilder
using System.Diagnostics;
using System.IO;
class Program
{
private static bool redirectStandardOutput = true;
private static string buildargument(string[] args)
{
StringBuilder arg = new StringBuilder();
for (int i = 0; i < args.Length; i++)
{
arg.Append("\"" + args[i] + "\" ");
}
return arg.ToString();
}
static void Main(string[] args)
{
Process prc = new Process();
prc.StartInfo = //new ProcessStartInfo("cmd.exe", String.Format("/c \"\"{0}\" {1}", Path.Combine(Environment.CurrentDirectory, "mapTargetIDToTargetNameA3.bat"), buildargument(args)));
//new ProcessStartInfo(Path.Combine(Environment.CurrentDirectory, "mapTargetIDToTargetNameA3.bat"), buildargument(args));
new ProcessStartInfo("mapTargetIDToTargetNameA3.bat");
prc.StartInfo.Arguments = buildargument(args);
prc.EnableRaisingEvents = true;
if (redirectStandardOutput == true)
{
prc.StartInfo.UseShellExecute = false;
}
else
{
prc.StartInfo.UseShellExecute = true;
}
prc.StartInfo.CreateNoWindow = true;
prc.OutputDataReceived += OnOutputDataRecived;
prc.ErrorDataReceived += OnErrorDataReceived;
//prc.Exited += OnExited;
prc.StartInfo.RedirectStandardOutput = redirectStandardOutput;
prc.StartInfo.RedirectStandardError = redirectStandardOutput;
try
{
prc.Start();
prc.BeginOutputReadLine();
prc.BeginErrorReadLine();
prc.WaitForExit();
}
catch (Exception e)
{
Console.WriteLine("OS error: " + e.Message);
}
prc.Close();
}
// Handle the dataevent
private static void OnOutputDataRecived(object sender, DataReceivedEventArgs e)
{
//do something with your data
Console.WriteLine(e.Data);
}
//Handle the error
private static void OnErrorDataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine(e.Data);
}
// Handle Exited event and display process information.
//private static void OnExited(object sender, System.EventArgs e)
//{
// var process = sender as Process;
// if (process != null)
// {
// Console.WriteLine("ExitCode: " + process.ExitCode);
// }
// else
// {
// Console.WriteLine("Process exited");
// }
//}
}
The code need to compile inside VS2007, using commandline csc.exe generated executable will not show console output correctly, or even crash with CLR20r3 error. Comment out the OnExited event process, the console output of the bat to exe will be more like the original bat console output.
Just for fun, here's my completed solution for getting PYTHON output - under a button click - with error reporting. Just add a button called "butPython" and a label called "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);
}
}

Categories