Pass arguments to running C# app - c#

I have a C# console app. This console app is intended to run in the background as long as my computer is running. At this time, that console app looks like this:
static void Main(string[] args)
{
while (true)
{
if (args.Length > 0)
{
Console.WriteLine("Args received!");
foreach(var arg in args)
{
Console.WriteLine("Arg: " + arg);
}
}
}
}
The console will initially load a lot of data. That's why I want to keep it running instead of always starting it. Still, once it's running, I need a way to "call" it again from another console window.
At this time, I'm thinking of starting the console app shown above using
START /B MyConsole.exe
from the command line. Then, I want to pass data do it in another console window like this:
MyConsole.exe --data [some info here]
This doesn't feel right at all. In fact, I'm fairly confident this won't work. Still, I need some way to have a running console app and pass data to that app from another console window via a command as shown above. The reason why I'm set on the approach shown above is ultimately I'm integrating with a third-party app that let's me execute command line commands. But, because my data is so large, I need to first have that app running.
How can I do this in C#?
Thank you!

The keywords here are inter process communication.
The easiest way to do this might be pipes.
Although not the newest and hippest technology anymore, I think your best bet on making pipes work easily in C# is WCF.
You could always host something else in your console application, like ASP.NET.
Your console application that is holding all the data might be better implemented as a windows service.
Maybe if you data is in fact just files, maybe using a memory mapped file might be easier than the inter process communication.
That said, communication between processes is a lot more complicated than command line parameters. None of those suggestions is particularly easy to implement (at least compared to a console application) and a lot of the details depend on the details of what you want to do.

I would create self-hosted ASP.NET Core Web Api application which will expose some rest endpoints so you could change your arguments based on the data sent (save it somewhere in memory, whatever). In the background there maybe an implementation of IHostedService running and doing some work in a loop based on the data sent.

Related

Is 'console type' of application suitable for my solution? ( C# )

I just started my internship as dev student.
I need to write a program in C# that will read a CSV productfeed, then parse it, map it and insert OR update this into a SQL Server database.
The program will run on a Windows VPS and has to be executed daily as the CSV will also be updated daily. I have to automate this process.
SO to come to my questions:
1. Can I go with a console application? (because I don't need any GUI)
2. Will a program like this with nested loops for insert/update crash or be too heavy on the DB as the CSV can contain +100k records?
Any guidance in the right direction is much apreciated
YES. You can develop a Console Application indeed. Doing something with Windows Forms or similar (i.e a C# app with a form and a single button with code.) would be a bad idea as you don't need a GUI and would be much harder to automate.
What options do you have?
Console application: Easy to develop. You can schedule it using Windows Task Scheduler.
Windows Service: A little bit harder to develop. It is much easier to control if it is running or not.
WCF or Restful Web Service: Harder to develop but more open if it needs to evolve in the future. Easier to interconnect with other servers as execution can be triggered externally.
NO, potentially no, although with bad code you can manage to create problems in SQL Server.
My advice: If you don't have much time/skills, go for Console App. If you can, create an asynchronous RESTFUL web service implementing GET to see the status of last/current execution, POST to trigger a new execution and return correct HTTP Response codes.
1. Can I go with a console application? (because i don't need any GUI)
Yes you can you Console Application and Task schedule for run this program daily.
Also you can write Windows Service - in this case your program will run in background.
2. Will a program like this with nested loops for insert/update crash or be too heavy on the DB as the CSV can contain +100k records?
100K+ rows its nothing for MS SQL. But sure you need write code correct. I will parse its and then Insert in db in multi thread. But it depends on what you need to do.
Technically you could use any application type you want, but If I'm gonna write this application I will pick Windows Service Application , because you want the application to run repeatedly in an automated way.
and for the performance, I don't think that hitting the database for every record it the best practice here may be you should look for Bulk Insert.

Passing Information Between Applications in C#

All. Firstly I am aware of the question Send data back to .exe from dll, however the answers there leave too many open ends for me and as I have no experience of what I am attempting I feel a new question is warranted.
I have an existing C# [All WinForms here] app that heavily relies on SQL. We have been asked (by clients) to provide an SQL Editor and library that can be used to develop and test SQL, but that can also be used to paste directly back in to the main application. The new SQLEditor is a multi-threaded application that parses and executes TSQL. I now have some things to consider; what is the best way to launch this second application from the main application::
Make the second app into a DLL and load into the main project, call the second app as a new form (SqlEditor sqlEd = new SqlEditor() etc.)? What are the implication in terms of thread bombardment, would I need [STAThread] - as I want both multithreaded apps to be available and active at the same time.
To launch as a separate .exe from the main application?
Depending on you advice; in either of the above cases - what is the best way I can pass information back to the main application from a click event in the second application whilst they are still both running and active [WCF, ApplicationDomains etc.]? Would the Observer design pattern come in to play here?
To make this question a little more appealing, here is the SQL Editor:
I plan to have a button which pastes the selected SQL back into the main application.
I am also aware that there are multiple questions here - which I apologise for. Thanks very much for your time.
If you need a simple way to do an outproc communication of two WinForms applications, then why don't you use the Clipboard with a custom format?
In the source application:
// copy the data to the clipboard in a custom format
Clipboard.SetData( "custom", "foo" );
In the destination application, create a timer to peek the clipboard:
private void timer1_Tick( object sender, EventArgs e )
{
// peek the data of a custom type
object o = Clipboard.GetData( "custom" );
if ( o != null )
{
// do whatever you want with the data
textBox1.Text = o.ToString();
// clear the clipboard
Clipboard.Clear();
}
}
This should fit your needs and it's still really simple as it doesn't require any heavyweight outproc communication mechanisms.
Another way of accomplishing intra-app communication is with the use of Windows messages. You define a global windows message id and use Windows API calls such as SendMessage and PostMessage.
Here's a simple article that explains how:
Ryan Farley's article "Communication between applications via Windows Messages"
This is in effect the observer pattern, receiving all the Windows messages being directed at the current Window and picking out the one you're listening out for.
In my experience this is definitely less flaky than the clipboard approach.
You have multiple choices for IPC(Inter Process Communication) such as:
Mailslot, NamedPipe, Memory Mapped File, Socket, Windows Messaging, COM objects, Remoting, WCF...
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365574(v=vs.85).aspx
http://en.wikipedia.org/wiki/Inter-process_communication
Some of them provide two-way communication, some needs considaration about system security(antivirus & firewall restrictions, you need to add the application as an exception in their settings).
Sending message through WM_COPYDATA can be done just by SendMessage, PostMessage is not supported, it means that the communication is sync.
Using outproc singleton COM object is another way, its not as simple as the other ways and both app. must be run on the same security context to access the same COM object.
Launching a separate application can coz some restrictions in communication methods or types of data you can pass, but separation of them will also protect them from their failures(App. crash will not close the other one).
If the two parts are always run on the same PC, using one of them as dll[inproc] is simpler. Using other techniques such as Socket, Remoting, WCF will provide you with more flexibility for communication, i.e. the two parts can run in different PCs with minor modifications...

Is it possible to fake windows console api?

I've written a ssh server in c# and I thought it'd be neat to hook up powershell as a shell. I've tried 2 methods to get this to work properly but both are far from perfect. Here's what I've tried:
Launch powershell.exe and redirect it's std(in/out). This doesn't
work well since powershell.exe detects it is redirected, changes
it's behaviour. What's more, it expects input data on the stdid, not
commands. So it uses the console api to read commands.
Host powershell in a "wrapper" application. This has the advantage of
being able to provide a "console" implementation to powershell (via
the PSHostRawUserInterface). This works better, but you can still invoke
commands (mostly real console applications) like "... | more", that expect
to be able to use the console api, and subsequently try to read from the
console of the wrapper process.
So what I'd like to do is have a set of functions replace the regular console input/output functions that console applications use, so I can handle them. But that seems rather drastic to the point of being a bad design idea (imo).
Right now I am on the idea of manipulating the console by sending the relevant keys with native/Pinvoke functions like WriteConsoleInput. I gather that it might be possible to fake the console that way. But I don't see how I would then "read" what happens on the console.
Also keep in mind, it's a service, so preferably it shouldn't spawn an actual console window, although perhaps in windows session 0 that wouldn't show up and not matter.
You've got PSSession for this purpose and the Enter-PSSession CmdLet. What will your SSH with Powershell do that PSSession is not doing ?
But if you want to do that here is a solution whithout writting anything : Using PowerShell through SSH
Edited 02/11/2011
PowerShell inside provide another way to do it whithout writting anything (free for personal usage).
Host03 sample, can perhaps provide basic code to do what you wat to do.
I installed PowerShellInside as suggested by JPBlanc, but didn't use it for very long. The one connection thing is just too limiting, and I don't like being limited (especially if that limitation is profit based but thats a whole other discussion i shouldn't get into). And despite being a solution to the original problem, it feels unsatisfactory because it doesn't solve the programming problem I ran into.
However, I did eventually manage to solve said problem, indeed by using the windows api calls in a wrapper process. Because there are quite a few pitfalls, I decided to anwser my own question and give others looking at the same problem some pointers. The basic structure is as follows:
Start the wrapper process with redirected stdin/-out (and stderr if you want). (In my case stdin and out will be streams of xterm control sequences and data, because that is the ssh way)
Using GetStdHandle() retrive the redirected input and output handles. Next SetStdHandle()'s to the CreateFile() of "CONIN$" and "CONOUT$", such that child processes inherits the the console and does not have the redirections of the wrapper process. (Note that a security descriptor allowing inheriting is needed for createfile)
Setup the console mode, size, title, Ctrl-C handler's, etc. Note: be sure to set a font if you want unicode support, I used Lucida Console (.FontFamily = 54, .FaceName = "Lucida Console"). Without this, reading the characters from your console output will return codepaged versions, which are horrible to work with in managed code.
Reading output can be done with the SetWinEventHook(), be sure to use out-of-context notification, because I'm pretty sure that having your managed application suddenly run in another process context/address space is a Bad Idea™ (I'm so sure that I didn't even try). The event will fire for every console window, not just your own. So filter all calls to the callback by window handle. Retrive the window handle of the current console application with GetConsoleWindow(). Also don't forget to unhook the callback when the application is done.
Note, upto this point be sure not to use (or do anything that causes the load of) the System.Console class, or things more than likely will go wrong. Usage after this point will behave as if the sub process had written to the output.
Spawn the needed sub process (Note, you must use .UseShellExecute = false or it will not inherit the console)
You can start providing input to the console using WriteConsoleInput()
At this point (or on a separate thread) you have to run a windows message loop or you will not recieve console event notification callbacks. You can simply use the parameterless Application.Run() to do this. To break the message loop, you must at some point post an exit message to your message loop. I did this with Application.Exit() in the subprocess's .Exited event. (Note use .EnableRaisingEvents for this to work)
Calls will now be made to your win event callback when something on your console changes. Pay attention to the scroll event, this might work somewhat unexpected. Also make no assumptions about synchronous delivery. If the sub process writes 3 lines, by the time you are processing the first event, the remaining 3 lines might already have been written. To be fair, windows does a nice job of composing events such that you don't get swamped with single character changes and can keep up with the changes.
Be sure to mark all PInvoke definitions with CharSet=CharSet.Unicode if they contain a character anywhere in the input or output. PInvoke.net missed quite a few of these.
The net result of all of this: a wrapper application for the windows console api. The wrapper can read/write the redirected stdin and stdout to communicate with the world. Ofcourse if you want to get fancy you could use any stream here (named pipe, tcp/ip, etc..). I implemented a few xterm control sequences and managed to get a fully working terminal wrapper that should be capable of wrapping any windows console process, translate the xterm input to input on the target application's console input and process the application's output to xterm control sequences. I even got the mouse to work. Starting powershell.exe as sub process now solves the original problem of running powershell in a ssh session. Cmd.exe also works. If anyone is interrested I'll see about posting the full code somewhere.

console app question

Updated for clarity, hopefully...
Yes, I was wondering if there are any use cases to say
Program p = new Program();
Yes I am referring to the Program class that comes with a new Console App template.
What are some use cases where you would want to instantiate the Program class in a c# console app?
If you, say, want to run multiple threads (as in a service app), each with their own copy of Program, it's useful to be able to:
Program p = new Program();
Main() won't automatically be called in these instances. This lets you, say, create service threads if the app is running as a service, or run some interactive console code within main(), depending on how the app was started. This is very handy when debugging services.
When you don't need a GUI -- when you don't need user input. Or you only need very simple user input (say..... in test code).
If your app will be running unattended on a server -- why have the overhead of an un-viewed form?
If good UI was not something you needed, but you do still need to display something.
I have written Win forms apps that could be executed silently... that is without showing the form, executing, then ending.
One very good reason might be to make sure an app can run when no GUI can be. On many linux servers and Windows Core installs GUI apps are not an option.

Passing parameters to start as a console or GUI application?

I have a console application that will be kicked off with a scheduler. If for some reason, part of that file is not able to be built I need a GUI front end so we can run it the next day with specific input.
Is there as way pass parameters to the application entry point to start the console application or the GUI application based on the arguments passed.
It sounds like what you want is to either run as a console app or a windows app based on a commandline switch.
If you look at the last message in this thread, Jeffrey Knight posted code to do what you are asking.
However, note that many "hybrid" apps actually ship two different executables (look at visual studio- devenv.exe is the gui, devenv.com is the console). Using a "hybrid" approach can sometimes lead to hard to track down issues.
Go to your main method (Program.cs). You'll put your logic there, and determine what to do , and conditionally execute Application.Run()
I think Philip is right. Although I've been using the "hybrid" approach in a widely deployed commercial application without problems. I did have some issues with the "hybrid" code I started out with, so I ended up fixing them and re-releasing the solution.
So feel free to take advantage of it. It's actually quite simple to use. The hybrid system is on google code and updates an old codeguru solution of this technique and provides the source code and working example binaries.
Write the GUI output to a file that the console app checks when loading. This way your console app can do the repair operations and the normal operations in one scheduled operation.
One solution to this would be to have the console app write the config file for a GUI app (WinForms is simplest).
I like the Hybrid approach, the command line switch appears to be fluff.
It could be simpler to have two applications using the same engine for common functionality. The way to think of it is the console app is for computers to use while the GUI App is for humans to use. Since the CLI App will execute first then it can communicate it's data through the config file to the GUI App.
One side benefit would be the interface to the processing engine would be more concise thus easier to maintain in the future.
This would be the simplest, because the Config file mechanism is easily available and you do not have to write a bunch of formatting and parsing routines.
If you don't want to use the Config mechanism, you could directly write JSON or XML Serialization to a file to easily transfer data also

Categories