locked
Application running both as Console and Windows Forms

    Question

  •  

    Hi,

    I'm creating my own compression utility in VB 2005. So, I'd like the user to be able to run my app from the command line (giving arguments to the executable) but also as a normal Windows Forms app (even checking if no arguments are passed in the command line, if the executable is launched in the console).

    I tried to create a Windows Forms project and then set the output as Console, but this way the Console window stays opened (and I don't want).

    I also tried to compile as Windows Forms (as it normally should) putting in a module a Sub Main, but this gets ignored since the startup object is necessarily the main form (and from Project Properties, the IDE doesn't let me change startup object to Sub Main).

    Should I try to compile from the command line (e.g.: compile as Windows Forms, startup object Sub Main)?

    Thanks in advance,

    Alessandro

    Saturday, November 25, 2006 11:12 AM

Answers

  • You can create a console window in a Windows Forms project.  Project + properties, turn off "Enable application framework" and set Startup object to "Sub Main".  Add a new module to your project and paste this code:

    Module Module1
      Private Declare Auto Function AllocConsole Lib "kernel32.dll" () As Boolean
      Public Sub Main()
        '--- Check if command line arguments were specified
        Dim args() As String = Environment.GetCommandLineArgs()
        If args.Length > 1 Then
          '--- Yep, create the console window and run the console mode logic
          AllocConsole()
          ConsoleMain(args)
        Else
          '--- Nope, run the normal Windows Forms startup code
          Application.EnableVisualStyles()
          Application.SetCompatibleTextRenderingDefault(False)
          Application.Run(New Form1)
        End If
      End Sub

      Private Sub ConsoleMain(ByVal args() As String)
        '--- This code runs when command line arguments were given
        Console.WriteLine("Command line = {0}", Environment.CommandLine)
        Console.WriteLine("Exe path = {0}", args(0))
        For ix As Integer = 1 To args.Length - 1
          Console.WriteLine("  Argument({0}) = {1}", ix, args(ix))
        Next
        Console.Write("Press ENTER to continue")
        Dim s As String = Console.ReadLine()
      End Sub

    End Module

    Modify the Application.Run() statement to create the proper startup form, if necessary.
    Saturday, November 25, 2006 1:49 PM
  • Make your Program.cs code look like this:

    using System;
    using System.Windows.Forms;

    namespace WindowsApplication1 {
      static class Program {
        [STAThread]
        static void Main(string[] args) {
          if (args.Length > 0) {
            // Command line given, display console
            AllocConsole();
            ConsoleMain(args);
          }
          else {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
          }
        }
        private static void ConsoleMain(string[] args) {
          Console.WriteLine("Command line = {0}", Environment.CommandLine);
          for (int ix = 0; ix < args.Length; ++ix)
            Console.WriteLine("Argument{0} = {1}", ix + 1, args[ix]);
          Console.ReadLine();
        }

        [System.Runtime.InteropServices.DllImport("kernel32.dll")]
        private static extern bool AllocConsole();
      }
    }
    Thursday, September 13, 2007 3:52 PM

All replies

  • one other way of doing it is to get the Environment.CommandLineArgs() which returns you any input the user gave at the command prompt. This returns a string array() which contains the arguments given by the user. It can be read from anywhere in the application, maybe form_load would be ok for you too.
    Saturday, November 25, 2006 1:35 PM
  • You can create a console window in a Windows Forms project.  Project + properties, turn off "Enable application framework" and set Startup object to "Sub Main".  Add a new module to your project and paste this code:

    Module Module1
      Private Declare Auto Function AllocConsole Lib "kernel32.dll" () As Boolean
      Public Sub Main()
        '--- Check if command line arguments were specified
        Dim args() As String = Environment.GetCommandLineArgs()
        If args.Length > 1 Then
          '--- Yep, create the console window and run the console mode logic
          AllocConsole()
          ConsoleMain(args)
        Else
          '--- Nope, run the normal Windows Forms startup code
          Application.EnableVisualStyles()
          Application.SetCompatibleTextRenderingDefault(False)
          Application.Run(New Form1)
        End If
      End Sub

      Private Sub ConsoleMain(ByVal args() As String)
        '--- This code runs when command line arguments were given
        Console.WriteLine("Command line = {0}", Environment.CommandLine)
        Console.WriteLine("Exe path = {0}", args(0))
        For ix As Integer = 1 To args.Length - 1
          Console.WriteLine("  Argument({0}) = {1}", ix, args(ix))
        Next
        Console.Write("Press ENTER to continue")
        Dim s As String = Console.ReadLine()
      End Sub

    End Module

    Modify the Application.Run() statement to create the proper startup form, if necessary.
    Saturday, November 25, 2006 1:49 PM
  •  

    Many thanks for both the answers! I will try them in a few minutes.. :-)

    Regards,

    Alessandro

    Saturday, November 25, 2006 3:13 PM
  • How would this be accomplished in C#?

    Thursday, September 13, 2007 3:27 PM
  • Make your Program.cs code look like this:

    using System;
    using System.Windows.Forms;

    namespace WindowsApplication1 {
      static class Program {
        [STAThread]
        static void Main(string[] args) {
          if (args.Length > 0) {
            // Command line given, display console
            AllocConsole();
            ConsoleMain(args);
          }
          else {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
          }
        }
        private static void ConsoleMain(string[] args) {
          Console.WriteLine("Command line = {0}", Environment.CommandLine);
          for (int ix = 0; ix < args.Length; ++ix)
            Console.WriteLine("Argument{0} = {1}", ix + 1, args[ix]);
          Console.ReadLine();
        }

        [System.Runtime.InteropServices.DllImport("kernel32.dll")]
        private static extern bool AllocConsole();
      }
    }
    Thursday, September 13, 2007 3:52 PM
  • Great! Thanks! That worked like a charm.

     

    I another question I would like to submit is if you run the Forms based application from an already existing console window, how can you use the existing console windows instead of allocating a new one. For example, if I run my Windows Forms application under the VS IDE all of the Console.WriteLine methods appear in the output window. But when I run the program in a console window, no output appears.

     

    In the end I could just write a console program, but I would love to leverage what I already have in terms of reusability.

     

    Again, thanks for the info! I've never used any of the DLL import stuff in C#.

    Thursday, September 13, 2007 5:46 PM
  • Visual Studio has a special facility (the Visual Studio Hosting Process) to redirect console output to the Output window.  You may have seen it running in Task Manager, its name is yourapp.vshost.exe.  You can achieve the same thing with Project + Properties, Application tab, Output type = Console application.  Your form will still work as normal, you just get an extra console window.  Check this thread to solve issues with focus.
    • Proposed as answer by Flem100 Saturday, April 03, 2010 1:28 PM
    Thursday, September 13, 2007 6:53 PM
  • Does anybody know how to do this in a c++ application? 

     

    The AllocConsole(); does not appear under System or System::Windows::Forms. 

     

    What namespace is it under? 

     

    thanks

     

    Sunday, September 16, 2007 5:50 PM
  • It is a Windows API function.  In C++, you'd only have to #include <windows.h>.  No special P/Invoke is required.
    Sunday, September 16, 2007 5:54 PM
  • Really great little piece of code.  Thanks!

    Thursday, November 06, 2008 4:22 AM
  • Visual Studio has a special facility (the Visual Studio Hosting Process) to redirect console output to the Output window.  You may have seen it running in Task Manager, its name is yourapp.vshost.exe.  You can achieve the same thing with Project + Properties, Application tab, Output type = Console application.  Your form will still work as normal, you just get an extra console window.  Check this thread to solve issues with focus.

    Worked for me. Thx
    Saturday, April 03, 2010 1:29 PM
  • Thanks a lot. It worked.

    Just had one more query. I don't want to create a new window for the console output. How can i use the same command window from where i am starting the application.

    Thursday, June 10, 2010 10:47 PM
  • I'd either make the original console output syntaxes you wanted into a .dll, or just import the existing project into you current project, include the namespace and run AltNamespace.Program.Main(); this may require you to pass args or remove args from the main function you are calling.

     

    Wednesday, February 01, 2012 5:35 PM