views:

500

answers:

6

I have a simple application that I would like to sort of automate via switches. But when I do run it via switches I don't really want a user interface showing. I just want it to run, do it's job, print stuff out in the console, and exit. On the other hand if I don't run it with any switches I want the user interface to pop up. And in this case I don't really want a console window hanging around in the background.

Is there any way I can do this, or do I have to create two separate projects, one Console Application and one Windows Application?

+4  A: 

Sure, just put a switch statement (or if else construction) in the static main(string[] args), based on arguments passed in command line. I also do this to switch between executing as a service or as a console...

NOTE: Set project type as Console App

[DllImport("kernel32.dll", SetLastError=true)]
private static extern int FreeConsole();    
[STAThread]
static void Main(string[] args)
        {
            if (args.Length == 0 && args[0] == "C") // Console
            {                    
                // Run as console code  
                Console.WriteLine("Running as Console App");
                Console.WriteLine("Hit any Key to exit");
                Console.ReadLine();
          }
            else
            {
                //Console.SetWindowSize(1,1);
                //string procName = Assembly.GetExecutingAssembly().FullName;
                //ProcessStartInfo info = new ProcessStartInfo(procName );
                //info.WindowStyle = ProcessWindowStyle.Minimized;

                // EDIT: Thanks to Adrian Bank's answer - 
                // a better approach is to use FreeConsole()
                FreeConsole();
                Application.Run(new MyForm());
            }
        }

EDIT: Thanks to Adrian Bank's answer, FreeConsole() is much better approach to "dispense" with Console window than just minimizing it...

Charles Bretana
How do you propose to implement that exactly?
Ed Swangren
I think the "Run as Console" and "Run as winforms" are the interesting points here though. The OP could have guessed this much.
Ed Swangren
+1: I don't see why this would have been downvoted... it's fairly simple, and effective. If each UI type (forms vs console) is it's own assembly, then the switch/if will load the appropriate assembly and run it.
SnOrfus
System.Windows.Forms.dll will need to be referenced for this to work.
Zach Johnson
I guess people downvote it because it's not a real console app (those are impossible according to Raymond Chen: http://blogs.msdn.com/oldnewthing/archive/2009/01/01/9259142.aspx), but I think the approach is suitable for the OP's problem. I just think that the IF-Condition is completely wrong - should be an || I think.
Michael Stum
Still no implementation, Raymond Chen seems to think this is a bad idea, and still this is at the top.
Ed Swangren
If you do this from a windows app you will not have access to stdin and stdout to read or write things to the console. If you mark your exe as a console application you will have a console hanging around.
Darryl Braaten
Honestly... this does not tell the OP anything.
Ed Swangren
Indeed, this either runs the app with a GUI or hides it completely allowing no user input or output as expected from a console appliaction.
Joshua
Added more implementation, running as windows app causes console window to appear, so I added code to dispense with it.
Charles Bretana
@Charles Bretana: No, you added code to minimize the console window, not "dispense with it". What you really want is `FreeConsole` (as in adrianbanks's answer), but that has its own issues...
Daniel Pryden
@Daniel, I'm pretty sure I knew what my code did, but I appreciate your clarifying it for me {grin}... Actually, I meant "dispense" as in "remove" from the screen". But thanx I didn't know about 'FreeConsole' - that is a better approach...
Charles Bretana
+2  A: 

They are two different paradigms, I don't think that using a command line switch like this is a good idea. Why not build the core logic into a console application and then call that from the GUI when needed? This would nicely separate the UI from the implementation but would still provide a way to use the Console app stand alone when needed.

Ed Swangren
Although I agree with this, it is sometimes helpful to have a single application that works as console or GUI - Visual Studio is a common example of this...
Reed Copsey
Fair point, hadn't thought of that. I would assume that is a pretty rare thing to need though.
Ed Swangren
I'm thinking about making two UIs, one console and one graphical, but yeah. Best solution is to have them in one. This way you can use it as a regular app, and using in a script for example.
Svish
But you can still do that if you have two separate programs, I don't see the need for wrapping it all into one.
Ed Swangren
+1  A: 

I believe the answer is no, or it was last time I looked into this problem.

The executable is marked as either a windowed application or a console application. You can see this in the properties for you project in Visual Studio, under application, Output type

You could simulate the behavior by having two application, a console application that if executed with no arguments launches the GUI application. You may see a console window flash, unless you ran in from an already open console.

Darryl Braaten
Visual Studio does that trick, there is a `devenv.exe` Windows application and a `devenv.com` console application.
0xA3
+4  A: 

From 'The Old New Thing'

How do I write a program that can be run either as a console or a GUI application?

You can't.

(I'll let you click on the article for the details of how to fake it)

Aaron
What's with the 2 drive-by downvotes?
Aaron
+1 for Raymond Chen reference.
Kyle Hodgson
A: 

Without implementing your own version of a console window the answer is no. When Windows loads you executable it decides whether or not to give you a console window based on data in the PE header. So you can make a windowed app not have a window but you can't make a windoed app have a console.

dkackman
+8  A: 

Whilst not exactly what you have asked, I've achieved the appearance of this behaviour in the past by using the FreeConsole pInvoke to remove the console window.

You set the output type of the project to be a console application. You then define the extern call to FreeConsole:

[DllImport("kernel32.dll", SetLastError=true)]
private static extern int FreeConsole();

Then, in you Main method you switch based on your conditions. If you want a UI, call FreeConsole before opening the form to clear the console window.

if (asWinForms)
{
    FreeConsole();       
    Application.Run(new MainForm());
}
else
{
    // console logic here 
}

A console window does briefly appear at startup, but in my case it was acceptable.

This is a bit of a hack though and has a bad smell, so I'd seriously consider whether you do want to go down this route.

adrianbanks
This is a very good approach for this situation. You can also AllocConsole (my deleted post showed this), but then your console is detached from the calling shell, if called from a shell.
Reed Copsey
Won't run well under Mono anymore then though, will it?
Svish