I am building a small program to help me when I use a server console for a game (hence I do not have the source for the console program).
I have the console starting up in the background and it redirects the output and I then write it in cute little textbox.
Problem is that It doesn't seem to give me the last line every time it makes an output.
This is some code from my server.cs:
public StreamWriter inputWriter;
public event EventHandler outputWritten;
string outtext = outputReader.ReadLine();
while (!process.HasExited)
{
// check for output from server
if (outtext != null)
{
if (outputWritten != null)
{
outputWritten(outtext, new EventArgs());
}
}
outtext = outputReader.ReadLine();
}
This is pretty much what the output would look like:
1) If it would run outside my program:
Welcome to the game server!
1 OptionA
2 OptionB
3 OptionC
Choose option:_ <-- this is where it should end waiting for input
2) If inside my program:
It would look like the above but wouldn't show the last line in stead it would end right at the empty line above the "Choose option:"
And when I give it an input it messes it up a bit and I get an output looking like "Choose option: Welcome to the game server!" where it should have written: "Choose option: 1" and on the next line given my a small question on how to proceed.
Related
I have a WPF application in which I am starting a process of Powershell from a different thread and redirecting the entire output to a textbox in the WPF window. The output of the window looks something like this:
STARTED PRODUCT 1 INSTALLATION
/* some lines here
more lines
*/
PRODUCT 1 INSTALLATION COMPLETE
What I want to do is that if, in between the STARTED and COMPLETE sections of text, any line or text containing "error" is spotted, I would like to update a particular icon and make it visible. Something like this:
if (text.Contains("error")
Product1RedCross.Visibility = Visibility.Visible;
else
Product1GreenTick.Visibility = Visibility.Visible;
This is showing kind of like a status by means of a red or green icon. If no error is spotted then it should display the green icon, showing that everything was fine.
My problem is that I have a bunch of different "Products". I would like to maybe take out chunks of text between "Started Product 1 installation" and "Product 1 installation complete" and check out if there is an error in there.
Otherwise, if an error is spotted, I won't be able to know for which product is the error being shown.
How can I achieve this and make it so that I can effectively determine where the error is and update the UI elements of that product accordingly.
My code for starting the process looks like this:
PowershellProcess.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
{
if (!string.IsNullOrEmpty(e.Data))
{
StringBuilderOutput.AppendLine(e.Data);
lock (this._myLockToken)
{
Dispatcher.BeginInvoke(
new ThreadStart(() => OutputTextBlock.Text = StringBuilderOutput.ToString()));
if (e.Data.Contains("PRODUCT 1 INSTALLATION STARTED"))
{
}
}
}
});
But here, I'm having trouble how I can work with sections of each product so that I can do UI operations without mixing other products up.
I have a C# winform application in which an optimization model is solved by OR-Tools. The optimization solver has the capability of sending the whole optimization process as stdout.This is done by:
Slvr.EnableOutput();
Solver.ResultStatus restatus = Slvr.Solve();
However, the solver does not automatically open up the console.
Currently, what I have done is:
Projects properties --> Application --> Output type --> Console Application
and the console is ready from the beginning till the end of the application run. Hence, that process stdout is automatically displayed.
What I want is to open the console exactly when the above part of code is run and display the stdout from the solver. Then wait for a key from the user to close the console and continue with the main application.
I guess your problem is you are trying to run the solver as part of the Winforms application, inside the GUI process right? But Console output is usually disabled in a Winforms application. You have basically two options:
use one of the options described here in this older SO answer to attach a console window for output to a Winforms application
split the application into two exe files: one command line program which runs the solver, and a Winforms part, just containing the UI. Then run the command line part as a separate process by System.Diagnostics.Process.Start, which allows finegrained control about output redirection. You may need the UI to pass parameters to the command line program, for example, by using a temporary file.
The second option is more work, especially for the communication between the GUI and the command line tool, but can be implemented easier in a way the GUI is not blocked, is more robust against bugs / program crashes in the solver part and performs usually better in case you want to introduce parallelization / run multiple solver processes at once.
Doc Brown has already answered your question, I'm only adding this to provide some code of how we implemented it here-- it's exactly what he suggests. We have a separate testPlugin.exe that get's started here. The communication is via files read and written on the file system. The console output gets captured in the "output handlers"
using System;
using System.Diagnostics;
using System.IO;
...
private void startTest()
{
int result = 2;
setFormStatus("working..."); // My method to inform the user with the form to wait.
getFormData(); // My method to get the data from the form
string errorMessage = null;
System.Diagnostics.Process testPlugInProcess = new System.Diagnostics.Process();
try
{
using (testPlugInProcess)
{
testPlugInProcess.StartInfo.UseShellExecute = false;
testPlugInProcess.StartInfo.FileName = System.IO.Path.Combine(assemblyDirectory, TestPlugInExe); // The name of the exe file
testPlugInProcess.StartInfo.CreateNoWindow = false;
testPlugInProcess.StartInfo.Arguments = getModelTestCommandLineArgs(); // My method to create the command line arguments
testPlugInProcess.StartInfo.RedirectStandardError = true;
testPlugInProcess.StartInfo.RedirectStandardOutput = true;
testPlugInProcess.OutputDataReceived += pluginTestOutputHandler;
testPlugInProcess.ErrorDataReceived += pluginTestOutputHandler;
testPlugInProcess.Start();
testPlugInProcess.BeginErrorReadLine();
testPlugInProcess.BeginOutputReadLine();
testPlugInProcess.WaitForExit();
result = testPlugInProcess.ExitCode;
}
setFormStatus("");
}
catch (Exception ex)
{
errorMessage = ex.Message;
}
testPlugInProcess = null;
}
Both the console and error output get written to the same file here, but you could separate them.
The plug-in handler looks like this:
private static void pluginTestOutputHandler(object sendingProcess,
DataReceivedEventArgs outLine)
{
if (!String.IsNullOrEmpty(outLine.Data))
{
for (int i = 0; i < numberOfTriesForWriting; i++)
{
try
{
using (StreamWriter sw = File.AppendText(lastPlugInTestTraceFilePath)) // The file name where the data is written.
{
sw.WriteLine(outLine.Data);
sw.Flush();
return;
}
}
catch (IOException)
{
System.Threading.Thread.Sleep(msToWaitBetweenTries);
}
}
}
}
using System;
class MainClass {
public static void Main() {
string name;
Console.Write("Hello World: ");
name = Console.ReadLine();
if (name != null && name == "Test") {
Console.WriteLine("Test input.");
} else {
Console.WriteLine("Test not input.");
}
}
}
Hi, above is my simple C# code. I'm new to C#, although I am not new to programming as a whole. When I try this code (which I know has redundancy in the if statement, that's not the point) it prints garbage.
The code works normally, it just starts off like this:
Hello World: [6n[H[J[6n
I have no clue why it's adding [6n[H[J[6n. I tried looking it up, but I'm really at a loss. This code was working a few days ago, so maybe it's a compiler issue.
If anyone could help out, that would be much appreciated.
those are ansi console control codes. in ansi, [6n is "query cursor position", [h is "home" and [j is "erase down" http://www.termsys.demon.co.uk/vtansi.htm
To me, it looks like you were possibly pressing keys like home/delete/etc, and whatever console app you are running in is displaying them instead of interpreting them.
what kind of console are you running it in? were you pressing other keys while it is waiting?
i have this program i need to make, where it runs a bat file. i got that far, so when i click the button it opens the bat. but 3 problems i encountered i have been trying to resolve for a few days now, the problem is that i need to get the output of the .bat and display it in a textbox, i got that, but it only displays the first and least line... then i need to run the .bat in the background. so you don't see the window. then i also need to be able to hit a second button to close it. the bat is a constant update, lets just say it reads a number then 5 seconds later adds 1 to that number and displays it again. and does this over and over till you close it. that would be a simple description of this
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "C:\\Users/jwoow/Desktop/Server/run.bat";
p.Start();
string output = p.StandardOutput.ReadToEnd();
this.RunResults.Text = output;
p.WaitForExit();
Try to just ask one specific question at a time.
Stopping the process
You can end the process by calling the CloseMainWindow. Method on the Process object. Like this:
p.CloseMainWindow();
Just hook up the button event handler and call this method to end the process.
Displaying outputted lines in a message box
The ReadToEnd method blocks until all lines are read. You will probably rather need a loop to read line at a time, like this:
StreamReader output = p.StandardOutput;
while (output.EndOfStream == false)
{
var line = output.ReadLine();
MessageBox.Show(line);
}
Avoid showing a console window
To avoid showing a console window you will need to add this before starting the process
p.StartInfo.CreateNoWindow = true;
I have a C# WPF GUI app (C#App1) which among other things, reads lines from a text file and displays its contents in a text box. I need to extend this to read the piped output data from a C++ console app(C++App2) which is run from the command prompt, and display its contents in the text box in the GUI. Please give insight on how to do this.
For Eg
cmd>C++App2 | C#App1
Now the GUI C#App1 should display the C++ Output data
Thanks
Try something like this:
class Program
{
static void Main(string[] args)
{
string s;
while ((s = Console.ReadLine()) != null)
{
Console.WriteLine(s);
}
}
}
The console.ReadLine will get the data from the output of the C++ program and it will print it back. If you want to handle the data from the C++ app, just remove the Console.WriteLine for something that can handle the string from "s". You might have to set a thread to be able to read from the console while not stopping the GUI in WPF.