【问题标题】:Winforms open console in Main without closing form?Winforms在Main中打开控制台而不关闭表单?
【发布时间】:2013-11-26 20:53:28
【问题描述】:

我在 C# 中创建了一个同时使用表单和控制台的应用程序,在 Program.cs 的 Main() 中调用:

[STAThread]
static void Main(string[] args)
{
  if (Form1.compile == 0)
        {
            Application.EnableVisualStyles();

            Application.SetCompatibleTextRenderingDefault(false);

            Application.Run(new Form1());

        }

        if (Form1.compile == 1)
        {
            Form1.compile = 0;
            int u;

            IntPtr ptr = GetForegroundWindow();

            GetWindowThreadProcessId(ptr, out u);

            Process process = Process.GetProcessById(u);
            AllocConsole();

            //a lot of code for the command prompt
        }
}

启动应用程序时,首先启动Form1。然后当 Form1 关闭时,它才会加载命令提示符和我放入其中的所有代码。

我的问题是,我如何仅通过按下 Form1 中的按钮来运行第二部分(编译 == 1 时)?是否有可能,因为 Main() 函数仅在启动时被调用,而 Application.Start(Program.Main()) 会出错?

按钮:

private void button1_Click(object sender, EventArgs e)
    {
       this.Close();  // Any way to open the console part without closing the form?         
     //this.Hide();
       compile = 1;
    }

注意:我尝试在控制台之后调用打开 Form1,但我也想在按下按钮时更新控制台,这不会发生。

编辑:对于未来的读者,解决方案只是将所有内容放在 mainform(或其他类)而不是 Main() 中,因为它不会自我更新,因此在启动后无法执行任何操作。

【问题讨论】:

  • 编译是静态的吗??
  • 我从Form1调用编译,所以它是静态的。 Main() 函数根本不会更新,我希望它在我按下 Form1 中的按钮时更新。
  • 只需调用 Application.Exit() 就足够了。 this.Close() 是一个非常不错的第二选择,但不清楚为什么它不会导致 Application.Run() 调用完成。
  • @Hans 好的,我最初认为 Application.Exit() 会关闭表单和控制台。
  • Application.Exit() 将导致Run() 完成并关闭所有打开的窗口,因此它应该可以工作。我有一个问题:当你的窗口从应用程序的 GUI 部分关闭时,你为什么不启动控制台?

标签: c# winforms console


【解决方案1】:

您应该简单地将处理控制台的代码从您的Main 方法中提取出来。创建一个负责在程序中创建/操作控制台的新类,并将Form1.compile == 1 中的代码复制到该类中。然后在Main 中,如果它应该创建控制台,只需调用该类,或者如果您想创建然后操作控制台,则从按钮单击事件中调用它。

【讨论】:

  • 但是我仍然需要更新 Main,以检查按钮是否被按下?除非原始创建的表单关闭,否则 Main 不会更新
  • @Bart 目前还不清楚您是否应该永远不要从 Main 或仅有条件地创建控制台。如果您想通过单击按钮显示控制台,只需从Main 中完全删除所有代码。如果您有时想在表单之前、之后或而不是显示表单时显示控制台,那么您需要在Main 中有代码。
  • 好的,我将在表单中创建控制台,然后从 Main() 中删除所有代码。谢谢。
【解决方案2】:

您可以在不触及 main() 的情况下执行以下操作。

        [System.Runtime.InteropServices.DllImport("kernel32.dll")]
        private static extern bool AllocConsole();

        private void button1_Click(object sender, EventArgs e)
        {
            AllocConsole();
            this.Hide();
            // Just call the console related methods in here
        }

【讨论】:

  • 不想冒犯,但我不认为我完全理解你,因为你说话的方式。能否举个代码示例?
  • 为什么这个工作而不是简单的 Form1.compile?它还给出了一个错误:无法使用实例引用访问编译;改为使用类型名称来限定它
【解决方案3】:

好的,让我试着解释一下到底发生了什么。

正如您所期望的那样,Main 方法按顺序执行。它执行一个命令,然后执行下一个命令,等等。但是,一旦您调用 Application.Run,​​您就会开始一个消息循环 - 基本上是一个大的while (true) { ... }。只要表单处于打开状态,这种情况就会持续。因此,如果您想在表单打开时完成某些操作,请不要将其放在 Application.Run 调用之后,只需将其放在按钮的 Click 事件处理程序中即可。

现在,我猜您希望能够在按下按钮时打开控制台,但即使在按钮没有被按下时也是如此。

最简单的方法是为您的控制台创建一个帮助类:

public static class ConsoleHelper
{
  static bool isCreated;

  [System.Runtime.InteropServices.DllImport("kernel32.dll")]
  private static extern bool AllocConsole();

  public static void PrepareConsole()
  {
    if (isCreated) return;

    AllocConsole();
    isCreated = true;
  }
}

现在,您只需在按下按钮时调用 ConsoleHelper.PrepareConsole()。

但是,如果您没有按下按钮,它显然不会创建控制台。您可以从 Main 函数中删除控制台初始化代码,只需在 Form 的 Closing 事件处理程序中调用 ConsoleHelper.PrepareConsole()。这样,您应该可以在表单中以及在关闭表单之后使用控制台。

如果这不是您想要的,您可能需要更好地解释自己,因为显然,有足够的模棱两可得到三个无法回答您问题的答案:D

【讨论】:

  • 有点晚了,但感谢您的解释。我没有对此进行测试,因为我已经设法得到了我想要的。
猜你喜欢
  • 2010-12-13
  • 2017-01-24
  • 1970-01-01
  • 2016-09-07
  • 1970-01-01
  • 1970-01-01
  • 2020-10-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多