【问题标题】:Windows Forms + commands from the console in C#C# 中来自控制台的 Windows 窗体 + 命令
【发布时间】:2010-03-06 17:45:19
【问题描述】:

我已经阅读了一些关于结合 Windows 窗体和控制台应用程序的程序的主题,但我的问题似乎还没有解决。是否可以从 cmd-line 运行程序并能够通过表单和 cmd-line 命令控制应用程序?意思是:

  • 应用程序的普通用户通过(Windows 窗体)表单控制应用程序,
  • 供调试和高级用户通过控制台控制应用程序(并可选择查看 Windows 窗体中发生的情况))

我知道我想要的东西很重要,而且可能意味着很多工作,但我仍然想知道如何正确地做到这一点。

【问题讨论】:

  • 您是否正在设想一个应用程序,它提供一个表单 UI 以及一个可以按需“弹出”的控制台?或者您是否正在设想一个可以通过一些程序可访问的界面从任意其他应用程序控制的表单应用程序?

标签: c# winforms debugging console


【解决方案1】:

这并不难,只需 P/Invoke AllocConsole() API 函数来创建您自己的控制台。例如,让您的 Program.cs 源代码文件如下所示:

  static class Program {
    [STAThread]
    static void Main() {
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);
#if DEBUG
      CreateConsole();
#endif
      Application.Run(new Form1());
    }

    static void CreateConsole() {
      var t = new System.Threading.Thread(() => {
        AllocConsole();
        for (; ; ) {
          var cmd = Console.ReadLine();
          if (cmd.ToLower() == "quit") break;
          // Etc...
        }
        FreeConsole();
      });
      t.IsBackground = true;
      t.Start();
    }
    [System.Runtime.InteropServices.DllImport("kernel32.dll")]
    private static extern bool AllocConsole();
    [System.Runtime.InteropServices.DllImport("kernel32.dll")]
    private static extern bool FreeConsole();
  }

【讨论】:

  • 我不明白开发人员在使用托管代码时如何在原生 API 上运行得如此之快......首先搜索框架,真的只有很少的原生 API 访问需求......
  • @BeowulfOF:请向我们展示您如何按需创建控制台窗口。
  • 你为什么要这样做?只需让您的 Winforms-App 再次启动,而不是启动 mainform 管道,而是将命令行参数传递给已经运行的应用程序 - 方法已经足够了,所有这些都可以管理。
  • 谢谢,AllocConsole 正是我想要的。我已经通过上面的代码组合和 MVP 模式的使用完成了我的任务 - 有时这是乏味的工作,但它工作正常。
【解决方案2】:

您只需要使用ApplicationContext 而不是表单本身来启动您的Windows 窗体应用程序。这样您就不再依赖于要显示的主窗体,并且可以像控制台应用程序一样工作。

您也可以自己创建一个命令行可执行文件并链接到 Windows 窗体库以使用它们。

另一种方法是使用启动 Windows 窗体应用程序的某种启动器,以及通过本地网络或其他进程间通信与 Windows 窗体应用程序通信的命令行工具,D-Bus 或类似的系统 - many ways lead to Rome...

【讨论】:

    【解决方案3】:

    是的,你想要的很有可能。你有选择。我能想到的一些……:

    1. 使用 UI 自动化编写可以连接到 Windows 窗体应用程序并对其进行控制的控制器应用程序。这是 Windows Vista 中的新功能。在 System.Windows.Automation 命名空间中打包了托管类,它首先在 WPF 中发布,然后到达 .NET 3.0。 (现在我想起来了,我不确定“Windows Vista 中的新功能”是否属实。它可能是“.NET 3.0 中的新功能”,这意味着它也适用于 Windows XP。嗯....) UI 自动化需要Windows 窗体应用程序没有代码更改,但它可能有点低级,因为您需要对每次鼠标单击或剪切/粘贴进行编程。见the answer to Stack Overflow question Is there a way to control a third-party EXE file from VB.NET?

    2. 修改您的 Windows 窗体应用程序以通过 WM_COPYDATA 接口公开其功能。然后您的客户端应用程序可以与之通信。同样,这里的模型是两个不同的应用程序,其中一个可以控制或询问另一个。 .NET Reflector tool 是这种方法的一个很好的例子。有一个 ReflectorController,作为the ReflectorAddins project on CodePlex 的一部分提供。控制器是一个命令行工具,可以向 Reflector 发送WM_COPYDATA 消息,告诉它打开一个新的程序集,导航到一个特定的类,等等。

      控制器的代码: http://reflectoraddins.codeplex.com/sourcecontrol/network/Show?projectName=reflectoraddins&changeSetId=29526#19979

      此方法适用于任何 Windows 窗体应用程序。您将需要重写 WndProc 方法。要了解如何操作,请查看The Code Project 文章Use WM_COPYDATA to send data to/from C++ and C# Windows processes

      我还使用这种方法构建了一个基于 Windows 窗体的进度监视器,可以直观地显示长时间运行的测试的进度。

    3. 在您的应用程序中,公开一个可以编程的 COM 服务器对象。这正是微软向应用程序公开 Office 功能的方式。 Office 自动化允许任何支持 COM 的程序(C#、VBScriptPowerShell、Perl、PHP 等)“驱动”Office 应用程序。在此过程中,Office 应用程序是可见的。这种方法还需要在您的 Windows 窗体应用程序中添加额外的代码;具体来说,您必须托管一个 COM 对象并将其连接到您的 UI 层。如果您想为超级用户提供最大的灵活性,这可能更可取 - 他们可以编写自己的脚本来驱动该组件。

    我确定还有其他选择。

    【讨论】:

    • +1 用于 WM_COPYDATA 方法并提供反射器插件示例链接。
    【解决方案4】:

    我记得看到 IronPython 被用于从 Python 的命令行界面 (IDLE) 控制 Windows 窗体的演示中。

    编辑: 我找不到原始视频,但这个视频应该展示了无需太多努力就可以做到的事情。 See this video 跳转到 19:00。

    【讨论】:

    • 很有意思,谢谢!但我正在寻找一种不使用任何新工具的解决方案。
    • 添加了发布视频的链接。在因为新工具而放弃这个想法之前,看看它可能会为您节省大量时间并提供强大的基础设施来满足您的需求。或者,如果您觉得离家更近,您可能想看看 PowerShell 而不是 IronPython。
    【解决方案5】:

    这是可能的。您将不得不考虑线程化 Windows 窗体表单,可能在同一进程中使用单独的 application domain。您可能会考虑创建一个代理对象(一种继承 MarshalByRefObject 的消息类)。

    【讨论】:

      【解决方案6】:

      通常在查看您的应用程序时,您有一个 UI 层和一个业务层(以及一个数据层,谁知道还有更多层)。您可以将控制台客户端视为一个 UI 层(具有简单的命令输入),将 Windows 窗体客户端视为另一个。

      只需在应用程序启动时检查命令行参数。如果指定了参数,则实例化简单的控制台类,否则实例化(可能更复杂的)Windows 窗体类。

      如果您希望您的更改反映在 Windows 窗体应用程序中(同时从控制台应用程序控制它),请使用数据绑定尽可能多地设置您的应用程序。让您的业务层反映您的应用程序中实际发生的情况。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多