I'd like for a single console application to spawn other console windows and output to different ones at different times inside of a C# console application. Preferably within one console application, I spawn some other consoles, write to them, and close them during the finally block of the original console application.
What's the ideal way to do this in C#?
I don't believe you can do this with a regular console application. The closest you could come would be to create a your own form in WinForms/WPF which behaved in roughly the same was as a normal console window.
I suppose you could spawn extra processes which each had their own console, and write to them via network connections or named pipes etc... it would be pretty ugly though.
You can do this with Auto/Manual EventWaitHandles in C# combined with countless other techniques. However, you should probably step back and see what you are trying to accomplish and see if a winform app would be a better fit. Maybe post more details and ask for ideas.
A single process can only ever have one true Standard In, Error and Out.
You can fake different ones, especially in .Net because after all they are presented as managed streams which would be fine at the push/pull and of the pipe. The problem is the output/input end i.e. the bit you might be piping to a file, or where you are requesting user input. These simply won't play ball since the OS supplies no multiplexing method itself.
Using simple means at best you could do something that sent output to multiple different windows which looked much like a console window.
With much complexity you would handle reading from them too. In essence you are writing a window which pretends to be a console, and getting it reasonably close to all the little intricacies of console windows is (increasingly) hard.
It would be simple to have (say) a fake console per thread by creating a class like so. I only bother with Out, In and Err follow easily from this.
public class MultiplexByThreadConsole : IDisposable
{
private readonly TextWriter originalOut;
private readonly TextWriter myOut = new IndividualMultiplex();
public MultiplexByThreadConsole()
{
this.originalOut = Console.Out;
Console.SetOut(this.myOut);
}
public void Dispose()
{
Console.SetOut(this.originalOut);
}
private class IndividualMultiplex : TextWriter
{
[ThreadStatic]
private readonly TextWriter actual;
// override all the required functions and any
// others you want to wrap
public override void Write(char c)
{
if (actual == null)
{
actual = MakeWhateverYouReallyWantToOutputTo();
}
actual.Write(c);
}
}
}
Then somewhere in Main (or wherever) do:
using(new MultiplexByThreadConsole())
{
// off you go all threads during this get their own faked console.
}
You would likely keep the In/Out/Err all pointing to some common objects writers/reader which was itself the fake console.
This is however pretty nasty. I would say that, if you truly want to launch things that look like separate consoles then you should actually do that and launch a new process for each one with a glue back end to manage them (somewhat similar to the concept of Chrome's back end processes per tab).
Related
I have a c# program that I want to run multiple copies simultaneously. They need to communicate to each other; basically they'll run to a point then check if any other program has reached this point yet and, if not, set a flag telling the other programs to wait until the first process completes. Then the other programs try to "take control"; the first one wins and the process repeats.
Note that I don't have a "master" program; they're all the same.
Using a back-end database I think would be too slow. I've considered using Memory Mapped files, but I'm concerned about two programs reading it and seeing that it's OK to proceed, but then they'll both try to write to the file simultaneously and something will break. I only need a flag that the programs can check and, if false, set to true in the same code block.
Ideally the solution will run fast and be not too complex.
Any suggestions would be greatly appreciated. Thanks.
You can use a named mutex for this. These are very lightweight:
using System;
using System.Threading;
namespace Demo;
public static class Program
{
static void Main()
{
using var handle = new Mutex(initiallyOwned:false, "EventNameHere");
while (true)
{
Console.WriteLine("Obtaining lock.");
handle.WaitOne();
Console.WriteLine("Obtained lock. Simulating work");
Thread.Sleep(4000);
Console.WriteLine("Signalling lock.");
handle.ReleaseMutex();
}
}
}
Try running several instances of that console application and you'll see that only one is simulating the work at once.
Note that this sample code is very simplistic - in the real world you will have to manage how the application shuts down and stops waiting for the mutex in order to avoid AbandonedMutexException
I have a simple console app that writes out status of various resources in a nicely formatted way.
This app is using some 3rd party components to connect to places.
Those components unfortunately do a lot Console.Writes (or some sort of logging) which all ends up intertwined with my messages.
I tried redirecting Console output (in hopes that i could filter non-mine messages), but that seems to work ONLY on my messages.
var sb = new StringBuilder();
TextWriter tw = new StringWriter(sb);
Console.SetOut(tw);
So this works in redirecting console writes, but only on the ones i did.. output from 3rd party components is still streaming to my screen.. any other ways to supress that?
The reason you're not able to redirect the output of the third party components is because you're calling redirect on your process, not theirs. To do this, loop over the processes, find the ones that are writing to the console and redirect their output.
using System.Diagnostics;
Process[] processlist = Process.GetProcesses();
foreach(Process theprocess in processlist){
// you'll actually need to use something like the process name or id here.
if (theprocess == MyThirdPartyComponentsProcess)
{
theprocess.StartInfo.UseShellExecute = false;
theprocess.StartInfo.RedirectStandardOutput = true;
}
}
You'll have to be running as administrator for this work.
I've thought of one fairly hacky way:
Capture the existing Console.Out so you can reuse it in your "real" writer
Create your own TextWriter implementation, which...
... when it's asked to write, checks whether the calling code is in your assembly. See Assembly.GetCallingAssembly
So long as you don't have inlining problems, you should be able to check the context, and drop any output you don't want. You'd probably have to call Console.Out.WriteLine directly instead of Console.WriteLine, mind you - otherwise the caller will be the Console class.
A better solution would be to change your code to use log4net or something similar, so you could get your output in a more configurable way, not on the console - assuming your own use is also logging. (If it's for interactive output, something like the above may be the only way...)
Since, there doesn't seem to be a reasonable quick way to suppress these, I went with plan B, that is deferring my messages to the end. This way all the logging gets through, and than i write out all the information i am interested in.
I broke it down into Success/Warn/Error methods
public static void WriteError(string message, params string[] args) {
writerTasks.Add(() => {
var c = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(message, args);
Console.ForegroundColor = c;
});
}
and at the end of the execution, i call this method to flush it out.
private static void WriteResults() {
foreach (var t in writerTasks)
t();
}
i do it this way, because i am changing text color depending on message type, which is contained within each action.
in my case this works great, since the information scrolls up hiding all the logging.. which in fact is also beneficial.. just didn't want it dispersed between the main output
I have a WPF application that can take a few optional command line arguments.
This application is also a single instance application (using a mutex to close any instances if one is already open).
What I want for it to do though, is if something tries to open the application with some cmd line args, that the application will do what it's suppose to do with those (in my application it opens different dialogs based on the cmd line).
What is the easiest way to achieve this?
In psedo code here is what i'm looking for
protected override void OnStartup(StartupEventArgs e)
{
bool mutexIsNew;
using (System.Threading.Mutex m =
new System.Threading.Mutex(true, "MyApplication", out mutexIsNew))
{
//if this is not the first instance of the app
if (!mutexIsNew)
{
//if there is some cmd line args
if (e.Args.Length > 0)
{
//send the args to the older instance so it can handle them
SendToOtherInstance(e.Args);
//shutdown this new instance
Application.Current.Shutdown();
}
}
}
base.OnStartup(e);
}
There are lots of implementations of single instance apps on Code Project, actually there are so many of them it's hard to decide which one you want...
I tried several solutions, and I really like this one. It makes it very easy to intercept command line parameters passed to the second instance.
Why don't you just send a Windows message in the WM_USER range. You'll need to do a bit of marshalling of the information but you can do that with GlobalAlloc, GlobalLock, etc. quite easily.
You may wish to consider reversing the logic, ie. close the already running instance and re-launch with your new parameters.
If you're using .net 4, you might consider memory mapped files for inter-process communication. The second instance could write some data to shared memory, set a system mutex to notify the original instance, then shut-down. See this overview of memory mapped files.
Or, simpler yet, write the command line arguments to a simple text file in a folder that is always monitored by the original instance. The original instances sees the new file, processes it, then deletes it. This approach works with any version of .net and would be easier to test/debug.
I am creating a custom .net hardware framework that will be used by other programmers to control some hardware. They will add a reference to our DLL to get to our hardware framework. I am in need of a shared class that will be accessed from multiple applications (processes).
The singleton pattern seems to be what I need but it only works for multiple threads inside your process. I could be completely wrong but here is an example of the C# code I currently have. I can't help to feel that the design is incorrect. I wish I could share more specific information but I can't.
I must stress that I will have no control over the customer application. The solution must be contained inside the framework (DLL) itself.
The Framework: (Shared DLL)
public class Resources
{
static readonly Resources m_instance = new Resources();
public string Data;
private Resources()
{
Data = DateTime.Now.ToString();
}
public static Resources Instance
{
get
{
return m_instance;
}
}
}
The Test Application: (eventually customer app)
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Press enter to capture the resource!");
Console.ReadLine();
var resources = Resources.Instance;
Console.WriteLine("\r\n{0}: {1}\r\n", Thread.CurrentThread.ManagedThreadId, resources.Data);
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += WorkerDoWork;
worker.RunWorkerAsync();
while (worker.IsBusy)
{
Thread.Sleep(100);
}
Console.WriteLine("Press enter to close the process!");
Console.ReadLine();
}
static void WorkerDoWork(object sender, DoWorkEventArgs e)
{
var resources = Resources.Instance;
Console.WriteLine("\r\n{0}: {1}\r\n", Thread.CurrentThread.ManagedThreadId, resources.Data);
}
}
The first launched application gives an output of:
Press enter to capture the resource!
1: 6/24/2009 8:27:34 AM
3: 6/24/2009 8:27:34 AM
Press enter to close the process!
The second application gives an output of:
Press enter to capture the resource!
9: 6/24/2009 8:27:35 AM
10: 6/24/2009 8:27:35 AM
Press enter to close the process!
Conclusion:
I would like to see both applications return the same string of the time of the first instantiation of the class.
As you can see the singleton works for the multiple thread inside the process but not cross processes. Maybe this can't be done for I can't seem to find any solution.
Yes it is possible to share a singleton amongst several processes. However you will need to take advantage of a technology which supports interprocess communication in order to achieve this result.
The most popular technologies which allow you to share out your object fairly directly are Remoting and WCF.
Giving an example of sharing a singleton with either of these is beyond the scope of an SO answer. But there are many tutorials on the web for each of these. Googling either technology plus singleton should put you on the right path.
You cannot use a singleton to sync across applications. Each runs in its own application space, and as a matter of security cannot access memory/objects/etc. from the other without a method of communication (like remoting) To sync the two they would have to remote into a third program.
To add to the Kevin's answer, your constructor for your class Resources should really be made private for it to be a true singleton, otherwise nothing is stopping someone from creating a new instance of the Resources class through the constructor. This doesn't solve your problem, but it does stop one from misusing the Singleton.
Simply calling a singleton property in a different assembly from two different processes will create different instances of that class.
But you can easily share information between processes using .Net Remoting, or fire interprocess events if you only need simple signaling (EventWaitHandle).
[Edit:] To make it look like a Singleton to your callers, you can expose a class which will internally use Remoting to instantiate a singleton, and then return the instance transparently. Here is an example which (I think) does that: http://www.codeproject.com/KB/dotnet/remotingsingleton.aspx
There are ways to do it as mentioned above. But it is clumsy if you use WCF or remoting. Please try interprocess thread sync techniques.
For more info read the online free e-book on threading
http://www.albahari.com/threading/
Specially see the cross process sync constructs here ...
http://www.albahari.com/threading/part2.aspx#_Synchronization_Essentials
I am writing a C# console application that connects to a server trough TCP, it uses a separate thread to listen for incoming messages from the server and I want it to write them to the console while at the same time reading a message from the console. I was able to do that, but I have a problem.
The console displays this while I type and a messages comes in:
msg from server
msg from server
my msmsg from server
g to server
And i want it to separate my message from the servers mesages like so:
msg from server
msg from server
msg from server
my msg to server
If I receive a message I still want to keep my typed message, but I don't want it to mix up with the received message, I want it to remain complete on the last line.
Can I do that? And how?
Can I shift my message to the end of the console, when a message from the server comes in?
I believe this is in fact possible with the standard .NET Console API, using a bit of hackery. What you need to do is create an asynchronous Read/ReadLine method (which I assume you have already done, judging by your post) and allow it to be cancelled as soon as new data arrives. I'm going to assume you're sending input line by line for now. The pseudocode for the "new data handler" might be something like this:
Save the current input buffer.
Cancel the current asynchronous read.
Reset the cursor position to the end of the last writing of new data.
Output the new data.
Save the cursor position.
Restart the asynchronous read event.
In particular, you'll need to mess around with Console.CursorLeft and Console.CursorTop properties. You might be able to avoid some of the hackery by interfacing with the Win32 API console functions directly, but it's possibly not worth the bother.
Hope that helps.
You can't do this directly via the BCL in C#. There are two main alternatives, though.
1) Turn this into a GUI app, and have separate input/output areas. This is the most "clear" option from a user's POV, but requires a GUI app instead of a console app.
2) P/Invoke into the console API directly. This gives you complete control of the console's view, point by point. See SetConsoleCursorPosition and WriteConsole, etc.
You need to use a lock on some object to stop both threads using the console at the same time. Declare something like this:
public static class ThreadSafeConsole
{
private static object _lockObject = new object();
public static void WriteLine(string str)
{
lock (_lockObject)
{
Console.WriteLine(str);
}
}
}
Now call ThreadSafeConsole.WriteLine instead of Console.WriteLine.
If I understand you correctly, you'd have to define what the beginning and ending of 'typing to console' is for your application so that you can still lock on an object while that is happening, and not inserting messages from your listener thread into your typed text.
public static Object consoleLock = new Object();
public static void Main(string[] args)
{
lock (consoleLock)
{
// now nothing can write to the console (if it's trying to lock onto it)
Console.WriteLine("Please Input Something");
// read from console
}
// now, your separate thread CAN write to the console - without
// interrupting your input process
}