C#: Is it possible to have a single application behave as Console or Windows application depending on switches?

前端 未结 7 2090
无人及你
无人及你 2020-12-09 21:25

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

相关标签:
7条回答
  • 2020-12-09 22:02

    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.

    0 讨论(0)
  • 2020-12-09 22:13

    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.

    0 讨论(0)
  • 2020-12-09 22:16

    You can, but with some drawbacks:

    You can prevent having this black window on start up if you compile for subsystem Windows.

    But then you have to attach the process to the calling console (cmd.exe) manually via AttachConsole(-1) http://msdn.microsoft.com/en-us/library/windows/desktop/ms681952%28v=vs.85%29.aspx

    This alone does not do the job. You also have to redirect the three std streams to the console via these calls:

    // redirect unbuffered STDOUT to the console
    lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
    hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
    
    fp = _fdopen( hConHandle, "w" );
    *stdout = *fp;
    setvbuf( stdout, NULL, _IONBF, 0 );
    
    fp = _fdopen( hConHandle, "r" );
    *stdin = *fp;
    setvbuf( stdin, NULL, _IONBF, 0 );
    
    // redirect unbuffered STDERR to the console
    lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
    hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
    
    fp = _fdopen( hConHandle, "w" );
    *stderr = *fp;
    setvbuf( stderr, NULL, _IONBF, 0 );
    
    // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
    // point to console as well
    ios::sync_with_stdio();
    

    Sample from: http://cygwin.com/ml/cygwin/2004-05/msg00215.html

    The problem with your WinMain call is that windows already has forked out your process so the calling cmd.exe console will have returned from your .exe already and proceed with the next command. To prevent that you can call your exe with start /wait myexe.exe This way you also get the return value of your app and you can check it with %errorlevel% as usual.

    If there is a way to prevent that process forking with subsystem windows please let me know.

    Hope this helps.

    0 讨论(0)
  • 2020-12-09 22:19

    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)

    0 讨论(0)
  • 2020-12-09 22:20

    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.

    0 讨论(0)
  • 2020-12-09 22:26

    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...

    0 讨论(0)
提交回复
热议问题