简体   繁体   English

C#中控制台的Windows Forms +命令

[英]Windows Forms + commands from the console in C#

I've read a few topics about programs that combine Windows Forms and console applications, but it seems my question hasn't been solved yet. 我已经阅读了一些关于组合Windows窗体和控制台应用程序的程序的主题,但似乎我的问题还没有解决。 Is it possible to run a program from cmd-line and to be able to control the application via forms and via cmd-line commands? 是否可以从cmd-line运行程序并能够通过表单和cmd-line命令控制应用程序? It means: 它的意思是:

  • for ordinary users of the application to control the application via (Windows Forms) forms, 对于通过(Windows窗体)表单控制应用程序的应用程序的普通用户,
  • for debugging and advanced users to control the application via the console (and optionally see what's happening in Windows Forms)) 用于调试和高级用户通过控制台控制应用程序(并可选择查看Windows窗体中发生的情况))

I know that what I want is quite a big deal, and it will probably mean a lot of work, but still I would like to know how to do it properly. 我知道我想要的东西是非常重要的,它可能意味着很多工作,但我仍然想知道如何正确地做到这一点。

It isn't difficult, just P/Invoke the AllocConsole() API function to create your own console. 这并不难,只需P / Invoke AllocConsole()API函数来创建自己的控制台。 For example, make your Program.cs source code file look like this: 例如,使您的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();
  }

You just need to start your Windows Forms application with an ApplicationContext instead of a form itself. 您只需要使用ApplicationContext而不是表单本身启动Windows窗体应用程序。 You are then not depending on the main form to be shown and can act like an console application. 然后,您不依赖于要显示的主窗体,并且可以像控制台应用程序一样工作。

You could also just create a command-line executable and link with the Windows Forms libraries yourself to use them. 您也可以自己创建一个命令行可执行文件并与Windows窗体库链接以使用它们。

Another way would be to use some kind of starter, that fires up the Windows Forms application, and a command line tool that communicates with the Windows Forms application over local networking, or some other inter-process communication, D-Bus or similiar systems - many ways lead to Rome ... 另一种方法是使用某种启动器,它启动Windows窗体应用程序,以及通过本地网络或其他一些进程间通信, D-Bus或类似系统与Windows窗体应用程序通信的命令行工具 - 很多方式导致罗马 ......

Yes, what you want is very possible. 是的,你想要的是非常可能的。 You have options. 你有选择。 Some I can think of...: 有些我能想到...:

  1. Use UI Automation to write a controller application that can connect to the Windows Forms application and control it. 使用UI自动化编写可以连接到Windows窗体应用程序并控制它的控制器应用程序。 This is new in Windows Vista. 这是Windows Vista中的新增功能。 There are managed classes packaged in the System.Windows.Automation namespace, which first shipped in WPF , which arrived in .NET 3.0. System.Windows.Automation命名空间中打包了托管类,它首先在WPF中提供 ,它到达.NET 3.0。 (Now that I think about it, I'm not sure "new in Windows Vista" is true. It may be "new in .NET 3.0" which implies it also works on Windows XP. Hmmm....) UI Automation requires no code change to the Windows Forms application, but it can be sort of low-level, because you need to program each mouse click or cut/paste. (现在我考虑一下,我不确定“Windows Vista中的新功能”是否属实。它可能是“.NET 3.0中的新功能”,这意味着它也适用于Windows XP。嗯......)UI自动化需要没有代码更改到Windows窗体应用程序,但它可能是低级别的,因为您需要编写每个鼠标单击或剪切/粘贴。 See the answer to Stack Overflow question Is there a way to control a third-party EXE file from VB.NET? 请参阅Stack Overflow问题的答案有没有办法从VB.NET控制第三方EXE文件? .

  2. Modify your Windows Forms application to expose its function via a WM_COPYDATA interface. 修改Windows窗体应用程序以通过WM_COPYDATA接口公开其功能。 Then your client application can communicate with it. 然后您的客户端应用程序可以与它通信。 Again, the model here is two distinct applications, one of which can control or interrogate the other. 同样,这里的模型是两个不同的应用程序,其中一个可以控制或询问另一个。 The .NET Reflector tool is a good example of this approach. .NET Reflector工具就是这种方法的一个很好的例子。 There's a ReflectorController, available as part of the ReflectorAddins project on CodePlex . 有一个ReflectorController,作为CodePlex上ReflectorAddins项目的一部分提供。 The controller is a command-line tool, that can send WM_COPYDATA messages to Reflector, to tell it to open a new assembly, navigate to a particular class, and so on. 控制器是一个命令行工具,可以将WM_COPYDATA消息发送到Reflector,告诉它打开一个新程序集,导航到一个特定的类,等等。

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

    This approach will work for any Windows Forms application. 此方法适用于任何Windows窗体应用程序。 You will need to override the WndProc method. 您需要覆盖WndProc方法。 To see how, check The Code Project article Use WM_COPYDATA to send data to/from C++ and C# Windows processes . 要查看方法,请查看代码项目文章使用WM_COPYDATA向/从C ++和C#Windows进程发送数据

    I also used this approach to build a Windows Forms-based progress monitor that can visually display the progress of long-running tests. 我还使用这种方法构建了一个基于Windows窗体的进度监视器,可以直观地显示长时间运行的测试的进度。

  3. Within your application, expose a COM server object that can be programmed. 在您的应用程序中,公开可以编程的COM服务器对象。 This is exactly how Microsoft exposes Office function to applications. 这正是Microsoft向应用程序公开Office功能的方式。 Office Automation allows any COM-capable program (C#, VBScript , PowerShell , Perl, PHP, etc.) to "drive" Office applications. Office Automation允许任何支持COM的程序(C#, VBScriptPowerShell ,Perl,PHP等)“驱动”Office应用程序。 The Office application is visible while that is happening. 发生这种情况时,Office应用程序可见。 This approach would also require additional code in your Windows Forms application; 此方法还需要Windows窗体应用程序中的其他代码; specifically you have to host a COM object and hook it up to your UI layer. 特别是你必须托管一个COM对象并将其连接到你的UI层。 This may be preferable if you want maximum flexibility for superusers - they can write their own scripts to drive that component. 如果您希望超级用户具有最大的灵活性,这可能是更可取的 - 他们可以编写自己的脚本来驱动该组件。

I'm sure there are other options. 我相信还有其他选择。

I remember seeing IronPython being used in a demo controlling Windows Forms from Python's command line interface ( IDLE ). 我记得在Python的命令行界面( IDLE )中使用IronPython来控制Windows Forms的演示。

Edit: I could not find the original video but this one should show what is possible without too much effort. 编辑:我找不到原始视频,但这个应该显示可能没有太多努力。 See this video and jump to 19:00. 观看此视频并跳至19:00。

This would be possible. 这是可能的。 You will have to look into threading the Windows Forms form, possibly with the use of a separate application domain within the same process. 您将不得不考虑线程化Windows窗体表单,可能在同一进程中使用单独的应用程序域 You might look into creating a proxy object (a kind of message class inheriting MarshalByRefObject). 您可以考虑创建一个代理对象(一种继承MarshalByRefObject的消息类)。

Normally when looking at your application, you have an UI layer and a business layer (and a data layer, and who knows many more layers). 通常,在查看应用程序时,您有一个UI层和一个业务层(以及一个数据层,谁知道更多层)。 You can think of the console client as an UI layer (with simple command inputs) and the Windows Forms client as another one. 您可以将控制台客户端视为UI层(使用简单的命令输入),将Windows窗体客户端视为另一个。

Simply check at application startup for command-line arguments. 只需在应用程序启动时检查命令行参数。 If there are arguments specified, instantiate the simple console classes, otherwise instantiate the (probably more complex) Windows Forms classes. 如果指定了参数,则实例化简单控制台类,否则实例化(可能更复杂的)Windows窗体类。

If you want your changes to reflect in the Windows Forms application (while controlling it from the console application) setup your applications as much as you can with databinding. 如果您希望更改反映在Windows窗体应用程序中(同时从控制台应用程序控制它),请尽可能使用数据绑定设置应用程序。 Let your business layer reflect what's actually going on in your application. 让您的业务层反映应用程序中实际发生的情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C#中的控制台和Windows窗体 - Console and Windows Forms in C# C#:从控制台应用程序更新Windows窗体上的标签文本 - C#: Update Label Text On Windows Forms From Console Application C# 从 windows forms 接收 richtextbox 中的控制台写入行 - C# Receiving console writeline in richtextbox from windows forms 从C#发出Powershell命令以进行控制台 - Issuing Powershell commands to console from C# 用于 Windows 窗体应用程序的 C# 覆盖 Console.Read() - C# Override Console.Read() for a Windows Forms app 任何人都可以将 C# 控制台应用程序代码转换为 Windows Forms 吗? - Can anyone convert C# console app code to Windows Forms? 有没有办法将我的控制台应用程序转换为C#中的Windows窗体应用程序? - Is there a way to convert my Console Application into a Windows Forms Application in C#? C#在Windows窗体或控制台上使用HttpListener和Request.ServerVariables - C# using HttpListener and Request.ServerVariables on Windows Forms or Console 如何将ac#console项目更改为Windows窗体应用程序项目? - how to change a c# console project to windows forms application project? 如何将 c# 控制台代码更改为 windows forms 应用程序 - How to change c# console code to windows forms application
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM