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.
Related
I'm trying to set the Text value of the Clipboard to the value of a string variable in a WPF application on .NET 4.7.2. If I debug the application and stop the execution right after the clipboard value has been saved then the value is there in clipboard and I can paste it as expected. If I continue execution then the value is wiped of sorts. For example, this is code that I can use to test with:
public void CopyToClipboard()
{
string temp = "test\ntest\ntest";
System.Windows.Clipboard.SetText(temp);
}
As you can see there are three lines that should be pasted. When I stop execution right after saving to the clipboard I will see an output like so:
test
test
test
If I continue execution (by hitting F5 or the "Continue" button in Visual Studio) then when I paste I get three lines of '\t' tabs. So, my three lines still exist, but the text has been erased.
Can anyone help me to get this resolved. What is causing me to loose the data in the clipboard?
I wrote a quick Linqpad script that just consists of the following line:
System.Windows.Clipboard.SetText("Hello");
And my clipboard is successfully set to "Hello" and stays that way after the program exits. Is there something else in your application that is modifying the clipboard?
Check this
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.clipboard.settext?redirectedfrom=MSDN&view=netframework-4.8#System_Windows_Forms_Clipboard_SetText_System_String_
public String SwapClipboardHtmlText(String replacementHtmlText)
{
String returnHtmlText = null;
if (Clipboard.ContainsText(TextDataFormat.Html))
{
returnHtmlText = Clipboard.GetText(TextDataFormat.Html);
Clipboard.SetText(replacementHtmlText, TextDataFormat.Html);
}
return returnHtmlText;
}
The Clipboard class can only be used in threads set to single thread
apartment (STA) mode. To use this class, ensure that your Main method
is marked with the STAThreadAttribute attribute.
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);
}
}
}
}
I want to write a program to monitor windows clipboard using C#. I found some post about this topic. According thread How to monitor clipboard content changes in C#? and Finding the handle to a WPF window, I write a demo using WPF. In all samples code I found, all of them are WinForm or WPF apps, and win32 api they interop with need window handle as parameters.
Such as api function SetClipboardViewer(HWND hWndNewViewer)
But in my scenario, I need my program run background as a service to monitor and collect clipboard content. How to monitor clipboard without window UI? Could you give me some suggestions? Thanks in advance.
According user1795804's suggestion, I write following test code
using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
public static class User32
{
[DllImport("User32.dll")]
public static extern IntPtr OpenClipboard(IntPtr hWndNewOwner);
[DllImport("User32.dll")]
public static extern IntPtr GetClipboardData(uint uFormat);
}
class Program
{
static void Main(string[] args)
{
int result = (int)User32.OpenClipboard(new IntPtr(0));
if (result == 0)
{
Console.WriteLine("error");
}
else
{
Console.WriteLine("success");
}
int returnHandle = (int)User32.GetClipboardData(1); //CF_TEXT 1
if (returnHandle == 0)
{
Console.WriteLine("can't get text data");
}
Console.ReadKey();
}
}
}
The result is I can open clipboard and seem to get a handle to date object.
But now I have two issue.
1. Although I have a handle to data object in clipboard, how can I get this data using handle? I can't find related function.
2. I need pass a proc function as callback so that it can receive message when system event raise. But I can't find counterpart in non-window app.
According to Microsoft, "There are three ways of monitoring changes to the clipboard. The oldest method is to create a clipboard viewer window. Windows 2000 added the ability to query the clipboard sequence number, and Windows Vista added support for clipboard format listeners. Clipboard viewer windows are supported for backward compatibility with earlier versions of Windows. New programs should use clipboard format listeners or the clipboard sequence number."
This GetClipboardSequenceNumber does not take any arguments and according to Microsoft,
"The system keeps a serial number for the clipboard for each window station. This number is incremented whenever the contents of the clipboard change or the clipboard is emptied. You can track this value to determine whether the clipboard contents have changed and optimize creating DataObjects. If clipboard rendering is delayed, the sequence number is not incremented until the changes are rendered."
This would fulfill your requirement of "I want to write a program to monitor windows clipboard using C#".
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.
[DllImport("kernel32.dll")]
private static extern Int32 AllocConsole();
I can open cmd.exe with this command. But i can open only one console window and write in it. How can i open another one? Is any clean and fast solution for opening two console windows?
So you can do multiple console windows within one single C# windows app, but to do so you would have to have a few things. Process.start(), and command-line parameters.
If you do it this way you can have your app create another instance of itself, but with different command line parameters to have each part do different things.
Here is a simplistic example of how to do it.
namespace Proof_of_Concept_2
{
class Program
{
static void Main(string[] args)
{
if (args.Length!= 0)
{
if (args[0] == "1")
{
AlternatePathOfExecution();
}
//add other options here and below
}
else
{
NormalPathOfExectution();
}
}
private static void NormalPathOfExectution()
{
Console.WriteLine("Doing something here");
//need one of these for each additional console window
System.Diagnostics.Process.Start("Proof of Concept 2.exe", "1");
Console.ReadLine();
}
private static void AlternatePathOfExecution()
{
Console.WriteLine("Write something different on other Console");
Console.ReadLine();
}
}
}
Here is a screenshot of it working.
In conclusion,
Getting 2 console windows is easy, getting them to talk to each other is a separate question in and of itself. But I would suggest named pipes. Relevant Stackoverflow Post
You have to change your thinking because the 2 Consoles once run on different processes don't automatically talk to each other. Whatever calculation you are doing on one of them, the other one is completely unaware.
You can do
Process.Start("cmd.exe");
as many times as you would like. Is this what you mean?
Unfortunately not, sorry — you cannot have more than one console window per application in Windows.
Run the Console app (first window)
Got to bin > debug and open the YourApplication.exe file (second window)