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


Answers:


101

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

using System.Windows.Forms;

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

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


7
根据MSdn的@Kenny,它一直都是
Marc Gravell

我使用vsCode(不是Visual Studio),因此我必须将以下xml添加到csproj文件中:<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp3.1</TargetFramework> <UseWPF>true</UseWPF> <UseWindowsForms>true</UseWindowsForms> </PropertyGroup> </Project> 注意Microsoft.NET.Sdk.WindowsDesktopUseWPF> true </ UseWPF>UseWindowsForms> true </ UseWindowsForms >
Shaybc

39

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

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

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

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


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

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

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

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


经过数小时的探索和实验,我得出的结论是,没有办法完美地做到这一点。没有任何副作用,您将无法同时获得控制台和窗口的所有优势。这是选择哪种副作用最讨厌您的应用程序目的的问题。


我还要补充一点,要在GNU / Linux的mono中获得终端输出,通常的窗口应用程序就足够了。即Console.WriteLine默认情况下始终工作。
Hi-Angel

26

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

}

5
-1,创建第二个控制台窗口并在其中运行命令。不是OP想要的。
tomfanning

8
实际上,它确实not创建了第二个控制台,因为您将项目的输出设置为Windows Applicationfirst,这当然不是OP所要求的,但很可能是他想要的,因为那样一来,当您不需要它时便没有控制台窗口
DrCopyPaste 2014年

按照广告宣传工作,尽管我没有得到应用程序图标,并且我不认为“当前工作目录”相同-有什么想法吗?
drzaus

“当前工作目录”是单独的问题,因为我将文件拖放到了exe文件上,这显然改变了cwd。还为这种方法找到了更多资源:调试输出的可能问题以及连接到现有控制台或创建方法的可能
drzaus

1
Plus1可以在2011年还原该人的-1。良好的解决方法
Gaspa79 '18

7

这很简单:

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

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


1
工作良好!如果需要检查击键,则必须在调用Console.ReadKey之前使用Console.KeyAvailable来检查键的可用性,否则,您将阻止事件循环(因此也阻止了表单)
wexman

5

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


2

这符合我的需求...

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

这将从新线程中开始,并且直到关闭表单后才释放线程。Task在.Net 4及更高版本中。


2

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

因此,您想在控制台应用程序中使用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 
}

1

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


1

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

为一个,

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

对于b,使用线程,或执行任何任务, 如何独立打开获胜表格?


1

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

Form form = new Form();
Form.Button.Text = "randomText";
System.Windows.Forms.Application.EnableVisualStyles();
System.Windows.Forms.Application.Run(form);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.