[c#] how to run a winform from console application?

How do I create, execute and control a winform from within a console application?

This question is related to c# winforms console-application

The answer is


I recently wanted to do this and found that I was not happy with any of the answers here.

If you follow Marc's advice and set the output-type to Console Application there are two problems:

1) If you launch the application from Explorer, you get an annoying console window behind your Form which doesn't go away until your program exits. We can mitigate this problem by calling FreeConsole prior to showing the GUI (Application.Run). The annoyance here is that the console window still appears. It immediately goes away, but is there for a moment none-the-less.

2) If you launch it from a console, and display a GUI, the console is blocked until the GUI exits. This is because the console (cmd.exe) thinks it should launch Console apps synchronously and Windows apps asynchronously (the unix equivalent of "myprocess &").


If you leave the output-type as Windows Application, but correctly call AttachConsole, you don't get a second console window when invoked from a console and you don't get the unnecessary console when invoked from Explorer. The correct way to call AttachConsole is to pass -1 to it. This causes our process to attach to the console of our parent process (the console window that launched us).

However, this has two different problems:

1) Because the console launches Windows apps in the background, it immediately displays the prompt and allows further input. On the one hand this is good news, the console is not blocked on your GUI app, but in the case where you want to dump output to the console and never show the GUI, your program's output comes after the prompt and no new prompt is displayed when you're done. This looks a bit confusing, not to mention that your "console app" is running in the background and the user is free to execute other commands while it's running.

2) Stream redirection gets messed up as well, e.g. "myapp some parameters > somefile" fails to redirect. The stream redirection problem requires a significant amount of p/Invoke to fixup the standard handles, but it is solvable.


After many hours of hunting and experimenting, I've come to the conclusion that there is no way to do this perfectly. You simply cannot get all the benefits of both console and window without any side effects. It's a matter of picking which side effects are least annoying for your application's purposes.


This worked for my needs...

Task mytask = Task.Run(() =>
{
    MyForm form = new MyForm();
    form.ShowDialog();
});

This starts the from in a new thread and does not release the thread until the form is closed. Task is in .Net 4 and later.


You can create a winform project in VS2005/ VS2008 and then change its properties to be a command line application. It can then be started from the command line, but will still open a winform.


It´s very simple to do:

Just add following attribute and code to your Main-method:

[STAThread]
void Main(string[] args])
{
   Application.EnableVisualStyles();
   //Do some stuff...
   while(!Exit)
   {
       Application.DoEvents(); //Now if you call "form.Show()" your form won´t be frozen
       //Do your stuff
   }
}

Now you´re fully able to show WinForms :)


You can create a winform project in VS2005/ VS2008 and then change its properties to be a command line application. It can then be started from the command line, but will still open a winform.


This worked for my needs...

Task mytask = Task.Run(() =>
{
    MyForm form = new MyForm();
    form.ShowDialog();
});

This starts the from in a new thread and does not release the thread until the form is closed. Task is in .Net 4 and later.


Its totally depends upon your choice, that how you are implementing.
a. Attached process , ex: input on form and print on console
b. Independent process, ex: start a timer, don't close even if console exit.

for a,

Application.Run(new Form1());
//or -------------
Form1 f = new Form1();
f.ShowDialog();

for b, Use thread, or task anything, How to open win form independently?


Here is the best method that I've found: First, set your projects output type to "Windows Application", then P/Invoke AllocConsole to create a console window.

internal static class NativeMethods
{
    [DllImport("kernel32.dll")]
    internal static extern Boolean AllocConsole();
}

static class Program
{

    static void Main(string[] args) {
        if (args.Length == 0) {
            // run as windows app
            Application.EnableVisualStyles();
            Application.Run(new Form1()); 
        } else {
            // run as console app
            NativeMethods.AllocConsole();
            Console.WriteLine("Hello World");
            Console.ReadLine();
        }
    }

}

All the above answers are great help, but I thought to add some more tips for the absolute beginner.

So, you want to do something with Windows Forms, in a Console Application:

Add a reference to System.Windows.Forms.dll in your Console application project in Solution Explorer. (Right Click on Solution-name->add->Reference...)

Specify the name space in code: using System.Windows.Forms;

Declare the needed properties in your class for the controls you wish to add to the form.

e.g. int Left { get; set; } // need to specify the LEFT position of the button on the Form

And then add the following code snippet in Main():

static void Main(string[] args)
{
Application.EnableVisualStyles();
        Form frm = new Form();  // create aForm object

        Button btn = new Button()
        {
            Left = 120,
            Width = 130,
            Height = 30,
            Top = 150,
            Text = "Biju Joseph, Redmond, WA"
        };
       //… more code 
       frm.Controls.Add(btn);  // add button to the Form
       //  …. add more code here as needed

       frm.ShowDialog(); // a modal dialog 
}

You should be able to use the Application class in the same way as Winform apps do. Probably the easiest way to start a new project is to do what Marc suggested: create a new Winform project, and then change it in the options to a console application


Here is the best method that I've found: First, set your projects output type to "Windows Application", then P/Invoke AllocConsole to create a console window.

internal static class NativeMethods
{
    [DllImport("kernel32.dll")]
    internal static extern Boolean AllocConsole();
}

static class Program
{

    static void Main(string[] args) {
        if (args.Length == 0) {
            // run as windows app
            Application.EnableVisualStyles();
            Application.Run(new Form1()); 
        } else {
            // run as console app
            NativeMethods.AllocConsole();
            Console.WriteLine("Hello World");
            Console.ReadLine();
        }
    }

}

I recently wanted to do this and found that I was not happy with any of the answers here.

If you follow Marc's advice and set the output-type to Console Application there are two problems:

1) If you launch the application from Explorer, you get an annoying console window behind your Form which doesn't go away until your program exits. We can mitigate this problem by calling FreeConsole prior to showing the GUI (Application.Run). The annoyance here is that the console window still appears. It immediately goes away, but is there for a moment none-the-less.

2) If you launch it from a console, and display a GUI, the console is blocked until the GUI exits. This is because the console (cmd.exe) thinks it should launch Console apps synchronously and Windows apps asynchronously (the unix equivalent of "myprocess &").


If you leave the output-type as Windows Application, but correctly call AttachConsole, you don't get a second console window when invoked from a console and you don't get the unnecessary console when invoked from Explorer. The correct way to call AttachConsole is to pass -1 to it. This causes our process to attach to the console of our parent process (the console window that launched us).

However, this has two different problems:

1) Because the console launches Windows apps in the background, it immediately displays the prompt and allows further input. On the one hand this is good news, the console is not blocked on your GUI app, but in the case where you want to dump output to the console and never show the GUI, your program's output comes after the prompt and no new prompt is displayed when you're done. This looks a bit confusing, not to mention that your "console app" is running in the background and the user is free to execute other commands while it's running.

2) Stream redirection gets messed up as well, e.g. "myapp some parameters > somefile" fails to redirect. The stream redirection problem requires a significant amount of p/Invoke to fixup the standard handles, but it is solvable.


After many hours of hunting and experimenting, I've come to the conclusion that there is no way to do this perfectly. You simply cannot get all the benefits of both console and window without any side effects. It's a matter of picking which side effects are least annoying for your application's purposes.


You can create a winform project in VS2005/ VS2008 and then change its properties to be a command line application. It can then be started from the command line, but will still open a winform.


You should be able to use the Application class in the same way as Winform apps do. Probably the easiest way to start a new project is to do what Marc suggested: create a new Winform project, and then change it in the options to a console application


Here is the best method that I've found: First, set your projects output type to "Windows Application", then P/Invoke AllocConsole to create a console window.

internal static class NativeMethods
{
    [DllImport("kernel32.dll")]
    internal static extern Boolean AllocConsole();
}

static class Program
{

    static void Main(string[] args) {
        if (args.Length == 0) {
            // run as windows app
            Application.EnableVisualStyles();
            Application.Run(new Form1()); 
        } else {
            // run as console app
            NativeMethods.AllocConsole();
            Console.WriteLine("Hello World");
            Console.ReadLine();
        }
    }

}

You should be able to use the Application class in the same way as Winform apps do. Probably the easiest way to start a new project is to do what Marc suggested: create a new Winform project, and then change it in the options to a console application


If you want to escape from Form Freeze and use editing (like text for a button) use this code

Form form = new Form();
Form.Button.Text = "randomText";
System.Windows.Forms.Application.EnableVisualStyles();
System.Windows.Forms.Application.Run(form);

It´s very simple to do:

Just add following attribute and code to your Main-method:

[STAThread]
void Main(string[] args])
{
   Application.EnableVisualStyles();
   //Do some stuff...
   while(!Exit)
   {
       Application.DoEvents(); //Now if you call "form.Show()" your form won´t be frozen
       //Do your stuff
   }
}

Now you´re fully able to show WinForms :)


Its totally depends upon your choice, that how you are implementing.
a. Attached process , ex: input on form and print on console
b. Independent process, ex: start a timer, don't close even if console exit.

for a,

Application.Run(new Form1());
//or -------------
Form1 f = new Form1();
f.ShowDialog();

for b, Use thread, or task anything, How to open win form independently?


All the above answers are great help, but I thought to add some more tips for the absolute beginner.

So, you want to do something with Windows Forms, in a Console Application:

Add a reference to System.Windows.Forms.dll in your Console application project in Solution Explorer. (Right Click on Solution-name->add->Reference...)

Specify the name space in code: using System.Windows.Forms;

Declare the needed properties in your class for the controls you wish to add to the form.

e.g. int Left { get; set; } // need to specify the LEFT position of the button on the Form

And then add the following code snippet in Main():

static void Main(string[] args)
{
Application.EnableVisualStyles();
        Form frm = new Form();  // create aForm object

        Button btn = new Button()
        {
            Left = 120,
            Width = 130,
            Height = 30,
            Top = 150,
            Text = "Biju Joseph, Redmond, WA"
        };
       //… more code 
       frm.Controls.Add(btn);  // add button to the Form
       //  …. add more code here as needed

       frm.ShowDialog(); // a modal dialog 
}

Here is the best method that I've found: First, set your projects output type to "Windows Application", then P/Invoke AllocConsole to create a console window.

internal static class NativeMethods
{
    [DllImport("kernel32.dll")]
    internal static extern Boolean AllocConsole();
}

static class Program
{

    static void Main(string[] args) {
        if (args.Length == 0) {
            // run as windows app
            Application.EnableVisualStyles();
            Application.Run(new Form1()); 
        } else {
            // run as console app
            NativeMethods.AllocConsole();
            Console.WriteLine("Hello World");
            Console.ReadLine();
        }
    }

}

You can create a winform project in VS2005/ VS2008 and then change its properties to be a command line application. It can then be started from the command line, but will still open a winform.


Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to winforms

How to set combobox default value? Get the cell value of a GridView row Getting the first and last day of a month, using a given DateTime object Check if a record exists in the database Delete a row in DataGridView Control in VB.NET How to make picturebox transparent? Set default format of datetimepicker as dd-MM-yyyy Changing datagridview cell color based on condition C# Inserting Data from a form into an access Database How to use ConfigurationManager

Examples related to console-application

How to run .NET Core console app from the command line ASP.NET Core configuration for .NET Core console application How to keep console window open How to navigate a few folders up? How to stop C# console applications from closing automatically? Could not load file or assembly ... An attempt was made to load a program with an incorrect format (System.BadImageFormatException) Can I write into the console in a unit test? If yes, why doesn't the console window open? What is the command to exit a Console application in C#? Can't specify the 'async' modifier on the 'Main' method of a console app Why is the console window closing immediately once displayed my output?