75

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

4

10 回答 10

104

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

using System.Windows.Forms;

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

重要的是[STAThread]你的Main()方法,需要完整的 COM 支持。

于 2008-11-10T12:44:37.963 回答
40

我最近想这样做,但发现我对这里的任何答案都不满意。

如果您按照 Marc 的建议将输出类型设置为控制台应用程序,则会出现两个问题:

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

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


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

但是,这有两个不同的问题:

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

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


经过数小时的狩猎和试验,我得出的结论是,没有办法完美地做到这一点。您根本无法在没有任何副作用的情况下获得控制台和窗口的所有好处。选择对您的应用程序而言最不烦人的副作用是一个问题。

于 2012-06-15T20:59:48.663 回答
26

这是我找到的最好的方法:首先,将您的项目输出类型设置为“Windows 应用程序”,然后 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();
        }
    }

}
于 2008-11-11T02:03:38.520 回答
6

做起来很简单:

只需将以下属性和代码添加到您的 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
   }
}

现在您完全可以显示 WinForms 了 :)

于 2011-12-01T20:26:10.737 回答
5

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

于 2008-11-10T12:44:41.643 回答
3

以上所有答案都有很大帮助,但我想为绝对初学者添加更多提示。

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

在解决方案资源管理器的控制台应用程序项目中添加对System.Windows.Forms.dll的引用。(右键单击解决方案名称->添加->参考...)

在代码中指定名称空间:using System.Windows.Forms;

在您的类中为您希望添加到表单的控件声明所需的属性。

例如int Left { get; set; } // need to specify the LEFT position of the button on the Form

然后在中添加以下代码片段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 
}
于 2018-06-13T00:07:23.087 回答
1

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

于 2008-11-10T12:46:23.140 回答
1

这满足了我的需求...

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

这从一个新线程中开始,并且在表单关闭之前不会释放线程。Task在 .Net 4 及更高版本中。

于 2015-07-09T03:29:09.983 回答
1

如果您想摆脱Form Freeze并使用编辑(如按钮的文本),请使用此代码

Form form = new Form();
Form.Button.Text = "randomText";
System.Windows.Forms.Application.EnableVisualStyles();
System.Windows.Forms.Application.Run(form);
于 2018-04-20T14:51:01.293 回答
0

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

为一个,

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

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

于 2015-08-22T11:03:57.923 回答