I\'m trying to talk to a command-line program from C#. It is a sentiment analyser. It works like this:
CMD> java -jar analyser.jar
>
This is not a general question, but rather a application-specific one. I just happened to be working on the same thing. We probably should not discuss about this here, but forgive me I just want to help.
The key point is that you need to enter the right arguments for the jar
var processInfo = new ProcessStartInfo("java.exe", "-jar SentiStrengthCom.jar stdin sentidata data201109/ scale"){ ... }
Below is a working solution:
// Start the java server, probably in a background thread
void bgw_DoWork(object sender, DoWorkEventArgs e)
{
string directory = ...; // the directory of jar
var processInfo = new ProcessStartInfo("java.exe", "-jar SentiStrengthCom.jar stdin sentidata data201109/ scale")
{
// Initialize properties of "processInfo"
CreateNoWindow = true,
UseShellExecute = false,
WorkingDirectory = directory,
RedirectStandardOutput = true,
RedirectStandardError = true,
RedirectStandardInput = true,
};
JavaSentiStrength = new Process();
JavaSentiStrength.StartInfo = processInfo;
JavaSentiStrength.Start();
Console.WriteLine("SentiStrengthCom Java is running...");
JavaSentiStrength.WaitForExit();
int exitCode = 0;
if (JavaSentiStrength != null) exitCode = JavaSentiStrength.ExitCode;
Debug.WriteLine("Java SentiStrengthCom closed down! " + exitCode);
JavaSentiStrength.Close();
JavaSentiStrength = null;
}
// A button click
private void btnRequest_Click(object sender, EventArgs e)
{
JavaSentiStrength.StandardInput.WriteLine("love you ");
string s_out = JavaSentiStrength.StandardOutput.ReadLine();
Debug.WriteLine("SentiStrengthCom output: " + s_out);
}
The output is
SentiStrengthCom output: 3 -1 2
Hope it helps!
What you're trying to do is to "redirect" the standard input and output channels for the process that you're launching. This will allow you to read from and write to the child process via C# streams.
To do so, you first need to set the RedirectStandardInput and RedirectStandardOutput fields in the ProcessStartInfo
class you use to start the child process:
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "otherprogram.exe";
p.Start();
Once that's done, p.StandardInput
and p.StandardOutput
will be StreamReader
s that are attached to the input and output of the child process. Depending on the exact input and output of the child process, you may need to be careful to avoid deadlocking (where your program is waiting for output while the other program is waiting for input, as an example). To avoid that, you can use the BeginOutputReadLine method to receive output asynchronously, if needed.
Here's a little demo showing how to do what you are asking.
This is a toy command line app that just reads from standard input and echos back to standard output:
class Echoer
{
static void Main(string[] args)
{
while (true)
{
var input = Console.ReadLine();
Console.WriteLine("Echoing: " + input);
}
}
}
This is another command line app that runs the above app, passing input to it, and reading its output:
class Program
{
static void Main(string[] args)
{
ProcessStartInfo processStartInfo;
processStartInfo = new ProcessStartInfo();
processStartInfo.CreateNoWindow = true;
// Redirect IO to allow us to read and write to it.
processStartInfo.RedirectStandardOutput = true;
processStartInfo.RedirectStandardInput = true;
processStartInfo.UseShellExecute = false;
processStartInfo.FileName = @"path\to\your\Echoer.exe";
Process process = new Process();
process.StartInfo = processStartInfo;
process.Start();
int counter = 0;
while (counter < 10)
{
// Write to the process's standard input.
process.StandardInput.WriteLine(counter.ToString());
// Read from the process's standard output.
var output = process.StandardOutput.ReadLine();
Console.WriteLine("Hosted process said: " + output);
counter++;
}
process.Kill();
Console.WriteLine("Hit any key to exit.");
Console.ReadKey();
}
}
If the app you are hosting does not simply produce a line of output in response to a line of input, then you can look at capturing output asynchronously using Process.BeginOutputReadLine (there's example code in the linked documentation).