【问题标题】:Program both as Console and GUI [duplicate]既可以作为控制台也可以作为 GUI 编程 [重复]
【发布时间】:2009-10-27 07:52:52
【问题描述】:

是否可以(如果可以,我该如何)使用 Delphi 2007 使单个程序既可以作为控制台应用程序也可以作为 GUI 版本运行?

我所追求的是,​​如果程序使用适当的命令行选项运行,它应该作为控制台程序运行,使用 WRITELN 将输出打印到控制台,但如果没有给出命令行参数,它应该运行为一个普通的 Delphi GUI 应用程序?

问题是,当作为控制台应用程序运行时,命令行解释器在允许您输入新命令之前等待应用程序终止,而从命令行启动的 GUI 应用程序会立即将您返回到命令行并GUI 应用程序在一个分离的进程中启动。我希望保留此行为。

我不介意这样的事情:

IF GUI THEN StartApplicationAsGUI(ParamStr(0))

即。我不介意如果需要,我必须使用某种形式的 EXECUTE 调用重新启动应用程序以在 GUI 模式下启动它,只要在 GUI 版本启动时命令行界面返回到命令行输入。

我更喜欢这样的解决方案/建议:


IF 控制台模式 THEN
RunConsole(参数)
其他开始
应用程序.初始化;
Application.CreateForm(...)
应用程序.运行;
结束

(反之亦然,即在 GUI 模式下以特殊方式做事)

这样我在做GUI界面的时候还是可以使用Delphi的IDE和VCL...

【问题讨论】:

    标签: delphi user-interface console


    【解决方案1】:

    在 Windows 上,这有点棘手。实际上,控制台应用程序和 GUI 应用程序之间的区别在于 PE 标头中的单个标志。您可以轻松编写创建窗口的控制台应用程序,但这样您始终拥有控制台窗口(虽然您可以将其隐藏,但当人们从 cmd 运行您的程序时,这并不好)。

    可以,但是如果需要,您可以编写一个 GUI 应用程序来创建一个控制台,使用 AllocConsole 函数:

    一个进程只能与一个控制台关联,因此如果调用进程已经有一个控制台,AllocConsole 函数会失败。进程可以使用FreeConsole 函数将自己与其当前控制台分离,然后它可以调用AllocConsole 来创建新控制台或AttachConsole 附加到另一个控制台。

    如果调用进程创建了子进程,则子进程继承新的控制台。

    AllocConsole 为新控制台初始化标准输入、标准输出和标准错误句柄。标准输入句柄是控制台输入缓冲区的句柄,标准输出和标准错误句柄是控制台屏幕缓冲区的句柄。要检索这些句柄,请使用 GetStdHandle 函数。

    此功能主要由图形用户界面 (GUI) 应用程序用来创建控制台窗口。 GUI 应用程序在没有控制台的情况下进行初始化。控制台应用程序使用控制台进行初始化,除非它们被创建为分离的进程(通过调用带有 DETACHED_PROCESS 标志的 CreateProcess 函数)。

    但是,当从cmd 运行时,这可能会导致另一个控制台窗口出现,而不是重新使用现有的。不知道那里有没有好的解决方案。

    【讨论】:

      【解决方案2】:

      IMO,这里最好的方法是让非可视类真正完成程序的工作。然后您可以从 GUI 程序调用它,也可以从单独的命令行程序调用它。这两个程序都只是您的类功能的包装器。

      这也迫使设计保持整洁 - 您的类必须与应用程序的 GUI 层分离。

      【讨论】:

      • 这种方法的问题在于,如果处理得当,它需要分发三个文件:1) 命令行可执行文件,2) GUI 可执行文件和 3) 包含相关核心的库文件该程序。我更喜欢单个可执行文件,最好的选择似乎是在标头中有一个带有控制台位的 GUI 程序,如果它需要作为 GUI 运行,则可以使用分离的控制台重新启动自身。就像提供的各种链接中的 ildasm 一样。
      • 好吧,我想说只有两个可执行文件是可行的。如果您构建包含 BPL 的 EXE,则无需分发任何“核心”文件 - 每个应用程序只需一个 exe。但显然你是知道你的部署需求的人;我很高兴 ildasm 的回答很有帮助。
      • 你是对的,它可以用 2 个文件来完成,但是核心功能代码必须编译到两个版本中,这 - IMO - 是一种浪费。根据核心功能的大小,这也会显着增加部署的规模。
      【解决方案3】:

      【讨论】:

      • 简短的回答(来自此链接)是:“你不能,但你可以尝试伪造它。”
      【解决方案4】:

      Windows 在控制台和 UI 应用程序的可执行文件头中具有不同的值(请参阅更多详细信息 here)。所以似乎不可能使相同的可执行文件在两种模式下工作。

      作为替代方案,您可以在您的 UI 应用中打开一个控制台,但它将是新的控制台,而不是您启动应用的那个控制台。

      【讨论】:

        【解决方案5】:

        AttachConsole() 可用于获取父控制台。 例如。如果应用程序是从 cmdline shell 启动的,则可以避免 AllocConsole():

        if not AttachConsole(ATTACH_PARENT_PROCESS)
        then AllocConsole;
        

        更多信息在这里: http://msdn.microsoft.com/en-us/library/windows/desktop/ms681952(v=vs.85).aspx

        【讨论】:

        猜你喜欢
        • 2015-11-03
        • 1970-01-01
        • 2010-12-11
        • 1970-01-01
        • 1970-01-01
        • 2016-11-18
        • 2020-10-03
        • 1970-01-01
        • 2013-07-24
        相关资源
        最近更新 更多