How do I let multiple consoles share input between one another? - c#

What I'm Trying to Achieve
I'm attempting to build a console game that has multiple console windows that would be displaying inventory, status effects, current map, and health. Another console would be the main one that gathers input to effect the other consoles. The reason I want to do it this way is so that the other consoles can be updating their "graphics" (or text) without disturbing the input flow.
What I've Tried So Far
So far, I've attempted to use System.IO's File, FileStream, StreamWriter, and StreamReader to communicate between the consoles via text files. The problem I've ran into is that, when the main console (the input console) is attempting to write inputs to a file--which is communicating with another console (the "graphics" console)--it throws an error because the "graphical" console is trying to read the input of the file (or vice versa).
I figured that making the FileStream's FileAccess be Readable would do the trick, but I ran into the same issue.
I think I could get this to work if I could communicate between the consoles to tell each other that one is done writing to or reading the file... kind of like a back and forth... "I'm writing to the file... okay, I'm done" "I'm reading the file... okay, I'm done" and the cycle continues...
So, in summary, I suppose, my question is how can I communicate between two consoles using files?
Possible Solutions I could try learning SQL, but I don't know if I'd end up running into the same issue... so, if I must learn SQL for this project, I suppose, that'd be my last option.
Thank you!

IPC (inter process communication) is the keyword you're looking for.
There are multiple ways to do IPC, e.g. shared memory, named pipes or similar. .NET has an IpcChannel which uses TCP or a named pipe if the destination is on the local PC.

Related

Best way to let multiple .NET apps communicate with each other

So, first of all sorry for my bad english.
Back to the questio, i have a main app, with a tab control, each tab contain another .NET exe. These need to send infos to the main app. Example:
Each exe in a tab have a random generated guid every second and the main app need to catch this and show in a listview or something as long the exe is "alive".
Currently i'm using SQLite, and everytime a new exe is started this one write in a table. Before closing it this exe remove the recod from the table.
In the mainwhile, the main app retrieve this update table and show the "alive" exe and the random generated guid (every second). All works fine, the problem is that i need to abandon this method and remove the two dll of SQLite.
What i tried is:
UDP socket between the N clients and the main app, but is not so stable. And sometime some exe got freezed. (using TCP will be so "heavy" for the only purpose to send a short string. Right?)
Changing the window text of the other exe and retrive it via processinfo, but is not updating it, i get it just the first time string.
So, there is a way for that? In local. Like, i don't know.. user32 sendmessage maybe? Or this method is too invasive for just a short string?
Considering that the N sub exe are process "inside" the main one, there is not a way to obtain infos from child process?
Thanks for your help!
UDP does not guarantee delivery of the packet by-desing. Unless you implement your own confirmation protocol above it. But implementation itself should be stable.
Using TCP will provide similar results. You'll just have to deal with reconnect stuff.
SendMessage/PostMessage is the easiest and straight forward method. But it will not allow you to pass string directly. Take a look at RegisterWindowMessage to register your own message and SendMessage with HWND_BROADCAST handle. And you'll have to send pointer to your string. Since SendMessage is synchronous you should be teoreticaly fine with disposing of that message, but I haven't tried that. Another option would be storing string somewhere-else (registry, file) and sending just update notification using SendMessage. And the main app will read and delete that registry/file record.
Self hosted WCF with netNamedPipeBinding should work as well. But that would be propably too robust solution.

Send data from Python to C#

I'm trying to send data from a python script to my c# application using a standard input stream. I also need to eventually send data back from my c# application to the another python script. I first tried to do this with a UDP Connection which works fine for a couple lines, but I have a fair amount of data to send (a few thousand lines) and a requirement for data integrity which UDP cannot provide. I could also write to a file, but that seems very inefficient.
One last restriction is that while my two applications are related I cannot setup a direct connection between them using something like IronPython as they are both spawned separately by a 3rd party application.
This is what I am currently trying, but it is not working. Similar to this question: Passing data between Python and C# without writing a file
p = subprocess.Popen(C_SHARP_EXECUTABLE_FILE_PATH, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
p.communicate(blob)
On my C# side I'm not entirely sure how to read this data, but I've tried using things like a loop around this:
Console.ReadLine()
or getting the standard input and reading from it directly using:
Console.OpenStandardInput();
The current issue is that as soon as I call p.communicate my Python script gets locked and doesn't proceed. If it's waiting for the line to be read, what do I need to do to make it stop waiting? I tried only providing the stdin parameter, but that didn't help.

Is there a way to monitor the state of a console application?

Is there a way to monitor the state of a console application?
I am trying to build a user interface which shows whether or not a console application is currently running on the server (processing files). If it is running, I would like to show the current state: how many files processed, what file currently being processed, etc.
The only way that I can think of doing this:
Create a text/xml file when application is started
Update text file with information about current state for each object it processes
Delete text file when the application is finished processing
To me, this doesn't seem like a very good or efficient way to do it. Is there a way to detect if the ClickOnce application is running, and perhaps some other way to access the "Messages" or Log of it to show the progress?
Note - I am also looking into using NodeJS to do this, but unsure if it has this capability.
First, you should consider writing this as a Windows service instead of a console application.
That said, scraping a log file that your application is writing is a reasonable approach. Just ensure that it never gets too big.
Alternatively, you could look at using custom performance counters. That would open the door to using System Monitor/perfmon as your monitoring tool, so no need to write any client code.
There are at least two ways to achieve that:
Your console application writes some logs, some state files, during its run, so other processes can read those files and understand what is going on in that console process.
Implement an IPC mechanism. There are different ways to do that. It may help you look in What is the easiest way to do inter process communication in C#?.

Inter-process communication: named pipes or status files

I'm building a tool that consists of a Webservice that will run commandline tools at specific times. On average there will be running 15-20 CL tools at the same time. Every CL tool runs no longer than about 0,5-1 minute on average. The webservice needs to be able to check each CL's status every 2-3 seconds or so.
I've got some advice about how to do this; named pipes looks likes the best "technical" solution. However I'm wondering if communicating with simple very small text "status" files would be a better, less complicated and less error-risk, way. I prefer the solution that is the most resource friendly.
Please advice.
Named pipes would be better. You might run into access problems with the two processes trying to access the small text file at once.
I did something similar before and here's what I did.
I start the command line process by setting ProcessStartInfo.RedirectStandardOutput to true. Then I start listening to the command line process' output by doing:
process.OutputDataReceived += dataReceivedEventHandler;
process.BeginOutputReadLine();
Then in my dataReceivedEventHandler, I parse DataReceivedEventArgs.Data to see if my console application sent me a "message" that begins with a tag that I created (ex: "[ServerProgress]10").
So basically, the applications are communicating through the console output. Not elegant, but it did the job for me.
Hope this helps.
For your situation, status checks - not a huge footprint there, I'd go with named pipes any day. Using memory >> using HDD here.

Polling directory on File Server

I need to write an application that polls a directory which contains images on a file server and display 4 at a time.
This application will be run up to 50 times across the network at the same time.
I'm trying to think of the best architecture to complete this requirement.
I was working on the idea of opening a file with read/write access and no file share allowed so that if another PC came in to read it it would error and it would have to move on to the next one, the problem is, is that I need to access all 4 images in sequence on the same pc ensuring other pc's dont try to open them. So for example if PC1 tries to open 1.jpg it needs to be able to open 1,2,3,4.jpg. If another PC comes in at the same time to read them I need a way for it to then open 5,6,7,8.jpg and so on and so on.
It seems a simple requirement but a nightmare to try and build successfully.
You're basically dealing with a race condition here, and I don't see a way to handle it from separate instances of your application running on separate machines unless you can guarantee your file naming will always follow a standard naming convention that would allow you to work with the sequence of 4 files using only the name of the first.
The best way to handle this would be using a centralized resource to manage access to your files, either a database as was suggested in a comment or else a service (such as WCF) that would "hand out" each set of 4 files.
What about creating a 1.jpg.lock file? The presence of a the file indicates the images are locked and any other instance of the application should skip that set.

Categories

Resources