如何从控制台应用程序运行winform?

时间:2021-05-22 20:47:40

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

如何在控制台应用程序中创建,执行和控制winform?

10 个解决方案

#1


84  

The easiest option is to start a windows forms project, then change the output-type to Console Application. Alternatively, just add a reference to System.Windows.Forms.dll, and start coding:

最简单的选择是启动Windows窗体项目,然后将输出类型更改为控制台应用程序。或者,只需添加对System.Windows.Forms.dll的引用,然后开始编码:

using System.Windows.Forms;

[STAThread]
static void Main() {
    Application.EnableVisualStyles();
    Application.Run(new Form()); // or whatever
}

The important bit is the [STAThread] on your Main() method, required for full COM support.

重要的一点是Main()方法的[STAThread],完全支持COM所需。

#2


30  

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:

如果您遵循Marc的建议并将输出类型设置为Console Application,则存在两个问题:

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.

1)如果你从资源管理器启动应用程序,你的表格后面会出现一个烦人的控制台窗口,在你的程序退出之前它不会消失。我们可以通过在显示GUI(Application.Run)之前调用FreeConsole来缓解此问题。这里的烦恼是控制台窗口仍然出现。它立即消失了,但是有一会儿就是这样。

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 &").

2)如果从控制台启动它并显示GUI,控制台将被阻止,直到GUI退出。这是因为控制台(cmd.exe)认为它应该同步启动控制台应用程序和异步启动Windows应用程序(相当于“myprocess&”的unix)。


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

如果将输出类型保留为Windows应用程序,但正确调用AttachConsole,则从控制台调用时不会获得第二个控制台窗口,并且在从Explorer调用时不会获得不必要的控制台。调用AttachConsole的正确方法是将-1传递给它。这会导致我们的进程附加到父进程的控制台(启动我们的控制台窗口)。

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.

1)由于控制台在后台启动Windows应用程序,它会立即显示提示并允许进一步输入。一方面这是个好消息,控制台没有在您的GUI应用程序上被阻止,但是如果您想要将输出转储到控制台并且从不显示GUI,则程序的输出在提示之后出现并且没有新提示完成后显示。这看起来有点混乱,更不用说你的“控制台应用程序”在后台运行,用户可以在运行时*执行其他命令。

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.

2)流重定向也被搞砸了,例如, “myapp some parameters> somefile”无法重定向。流重定向问题需要大量的p / Invoke来修复标准句柄,但它是可以解决的。


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.

经过几个小时的狩猎和实验,我得出的结论是,没有办法完美地完成这项工作。你根本无法获得控制台和窗口的所有好处,没有任何副作用。这是一个挑选哪些副作用最不适合您的应用程序的问题。

#3


22  

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.

这是我发现的最佳方法:首先,将项目输出类型设置为“Windows Application”,然后将P / Invoke AllocConsole设置为创建控制台窗口。

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();
        }
    }

}

#4


6  

It´s very simple to do:

这很简单:

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

只需将以下属性和代码添加到您的Main方法:

[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 :)

现在你完全能够展示WinForms :)

#5


4  

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.

您可以在VS2005 / VS2008中创建一个winform项目,然后将其属性更改为命令行应用程序。然后可以从命令行启动它,但仍然会打开一个winform。

#6


0  

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

您应该能够像Winform应用程序一样使用Application类。开始一个新项目最简单的方法可能是做Marc建议的:创建一个新的Winform项目,然后在选项中将其更改为控制台应用程序

#7


0  

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.

这将在新线程中启动from,并且在窗体关闭之前不会释放线程。任务在.Net 4及更高版本中。

#8


0  

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.

它完全取决于您的选择,以及您的实施方式。一个。附加过程,例如:在表格上输入并在控制台上打印b。独立进程,例如:启动计时器,即使控制台退出也不要关闭。

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?

对于b,使用线程或任务,如何独立打开win表单?

#9


0  

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

如果要退出Form Freeze并使用编辑(如按钮的文本),请使用此代码

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

#10


0  

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:

因此,您希望在控制台应用程序中对Windows窗体执行某些操作:

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

在解决方案资源管理器中的Console应用程序项目中添加对System.Windows.Forms.dll的引用。 (右键单击Solution-name-> add-> Reference ...)

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

在代码中指定名称空间: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

例如int Left {get;组; } //需要在Form上指定按钮的LEFT位置

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

然后在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 
}

#1


84  

The easiest option is to start a windows forms project, then change the output-type to Console Application. Alternatively, just add a reference to System.Windows.Forms.dll, and start coding:

最简单的选择是启动Windows窗体项目,然后将输出类型更改为控制台应用程序。或者,只需添加对System.Windows.Forms.dll的引用,然后开始编码:

using System.Windows.Forms;

[STAThread]
static void Main() {
    Application.EnableVisualStyles();
    Application.Run(new Form()); // or whatever
}

The important bit is the [STAThread] on your Main() method, required for full COM support.

重要的一点是Main()方法的[STAThread],完全支持COM所需。

#2


30  

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:

如果您遵循Marc的建议并将输出类型设置为Console Application,则存在两个问题:

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.

1)如果你从资源管理器启动应用程序,你的表格后面会出现一个烦人的控制台窗口,在你的程序退出之前它不会消失。我们可以通过在显示GUI(Application.Run)之前调用FreeConsole来缓解此问题。这里的烦恼是控制台窗口仍然出现。它立即消失了,但是有一会儿就是这样。

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 &").

2)如果从控制台启动它并显示GUI,控制台将被阻止,直到GUI退出。这是因为控制台(cmd.exe)认为它应该同步启动控制台应用程序和异步启动Windows应用程序(相当于“myprocess&”的unix)。


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

如果将输出类型保留为Windows应用程序,但正确调用AttachConsole,则从控制台调用时不会获得第二个控制台窗口,并且在从Explorer调用时不会获得不必要的控制台。调用AttachConsole的正确方法是将-1传递给它。这会导致我们的进程附加到父进程的控制台(启动我们的控制台窗口)。

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.

1)由于控制台在后台启动Windows应用程序,它会立即显示提示并允许进一步输入。一方面这是个好消息,控制台没有在您的GUI应用程序上被阻止,但是如果您想要将输出转储到控制台并且从不显示GUI,则程序的输出在提示之后出现并且没有新提示完成后显示。这看起来有点混乱,更不用说你的“控制台应用程序”在后台运行,用户可以在运行时*执行其他命令。

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.

2)流重定向也被搞砸了,例如, “myapp some parameters> somefile”无法重定向。流重定向问题需要大量的p / Invoke来修复标准句柄,但它是可以解决的。


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.

经过几个小时的狩猎和实验,我得出的结论是,没有办法完美地完成这项工作。你根本无法获得控制台和窗口的所有好处,没有任何副作用。这是一个挑选哪些副作用最不适合您的应用程序的问题。

#3


22  

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.

这是我发现的最佳方法:首先,将项目输出类型设置为“Windows Application”,然后将P / Invoke AllocConsole设置为创建控制台窗口。

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();
        }
    }

}

#4


6  

It´s very simple to do:

这很简单:

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

只需将以下属性和代码添加到您的Main方法:

[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 :)

现在你完全能够展示WinForms :)

#5


4  

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.

您可以在VS2005 / VS2008中创建一个winform项目,然后将其属性更改为命令行应用程序。然后可以从命令行启动它,但仍然会打开一个winform。

#6


0  

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

您应该能够像Winform应用程序一样使用Application类。开始一个新项目最简单的方法可能是做Marc建议的:创建一个新的Winform项目,然后在选项中将其更改为控制台应用程序

#7


0  

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.

这将在新线程中启动from,并且在窗体关闭之前不会释放线程。任务在.Net 4及更高版本中。

#8


0  

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.

它完全取决于您的选择,以及您的实施方式。一个。附加过程,例如:在表格上输入并在控制台上打印b。独立进程,例如:启动计时器,即使控制台退出也不要关闭。

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?

对于b,使用线程或任务,如何独立打开win表单?

#9


0  

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

如果要退出Form Freeze并使用编辑(如按钮的文本),请使用此代码

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

#10


0  

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:

因此,您希望在控制台应用程序中对Windows窗体执行某些操作:

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

在解决方案资源管理器中的Console应用程序项目中添加对System.Windows.Forms.dll的引用。 (右键单击Solution-name-> add-> Reference ...)

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

在代码中指定名称空间: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

例如int Left {get;组; } //需要在Form上指定按钮的LEFT位置

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

然后在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 
}