Passing parameters to start as a console or GUI application? - c#

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

Related

C# Systems.Net library vs. command line networking tools

For part of a C# application I am executing some relatively simple networking commands. (ping, ipconfig, tracert, nslookup, etc.)
I have read this answer on when to use C# vs CMD/PowerShell in the general sense:
https://stackoverflow.com/a/4188135/8887398
However, I'm wondering particularly for networking, and the Systems.Net library, is there any major advantage in taking the time to write code to implement these in C# as opposed to creating a new command line Process() within a C# app and executing it that way? (The Process() route is really simple/easy to code within C# app)
Question: What are my main advantages of implementing networking commands with the C# Systems.Net library vs creating a new Process() within a C# app and proceed internally as if you were using the command line?
There is certainly nothing wrong with starting a process. You can even start PowerShell and use that for sequences of actions that are easy to do in PowerShell.
Starting a process is not as easy as you might think.
You need to read both standard output and error for example. Else, the process will hang randomly. Doing this is surprisingly hard.
Getting results from commands is harder compared to using a .NET class. In .NET you get objects and exceptions back. A process can only send you text and an error code.
There is also more overhead. Whether that matters depends on the frequency of such operations.
You could leave child processes orphaned. The best solution is using Windows Job Object to kill the child tree when the parent exits.
So it depends on the specific case. I would definitely do a ping from C# since that is very easy to do. Other commands might benefit more from starting a process.

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.

How would I create a long running process in C#?

This may seem very elementary, but I don't really have any experience in this realm - all my experience has been on the web side of things.
I need to create a process of some sort that will repeatedly query an API (around 5 times a second), get the results from the API (in JSON format), and then my process will do what it needs to do with the results (in my case, insert them into a SQL database). These details don't really matter to the scope of the question I have, I just want to give you an idea on what I'm trying to achieve in case someone wants to recommend a better way of doing it.
My first thought was to create a console app that basically never quits (unless I specifically tell it to). Is a console app the way to go for this? The idea is I'll have a VM set up which will host my solution, including this "process" I create. I'm not all too familiar with Windows Services, or Windows Tasks, but I probably need to write some custom code so therefore I imagine I can't use the Windows Task Scheduler, am I right?
Once options would be to create a Windows Service which is the OS-level implementation of a long running process. To do so in C# you may wish to read through some tutorials online, perhaps starting with the MSDN Walkthrough. You should also read about Windows Services in general and the differences between a service and a regular user process (mainly the fact that services have no UI and can't interact with the user directly, and some of the other security considerations).
Other options may be to leverage a framework such as WCF or similar.

Automation in c# .Net

I need to write a program in .NET which runs every few hours and does some task. It does not require user interaction but it needs a configuration file like App.config where I can put that configuration information.
So should I write console program in C# ( like php or perl script) and schedule it in task manager ( like crontab) or write a Windows Service or something else?
If you want scheduling capabilities and that schedule needs to be very configurable, a windows scheduled task does that pretty well. You would write that as a console app.
However, I would suggest a service for most things. Here is a great tutorial that talks about how to create windows services. Its much easier than you think.
http://www.switchonthecode.com/tutorials/creating-a-simple-windows-service-in-csharp
My suggestion would be to go for the console app and use the task manager.
It saves you from having to implement a custom timer
It gives you elaborate control over timing
It saves you from having to implement an UI
It gives you automation options, like piping in- and output at the command line
Depending on the complexity of your task the best option would be to create an application which can be run via a task scheduler. If you need to run something every few hours a windows service would also work, but remember if you create a windows service then you will have to use a timer control within your application which might hang up without giving any clues. There are lots of examples for both the concepts and instead of using windows service you can use Window Communication Foundation (WCF).

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.

Categories