Win32 GUI应用程序,当以" app.exe --help"调用时将使用情况文本写入标准输出

时间:2020-03-05 18:50:51  来源:igfitidea点击:

如何创建执行以下操作的Windows应用程序:

  • 当没有命令行参数调用时,它是一个常规的GUI应用程序
  • 指定可选的" --help"命令行参数会导致应用将用法文本写入stdout,然后终止
  • 它必须是单个可执行文件。通过使控制台应用程序exec成为第二可执行文件,不会作弊。
  • 假设主要应用程序代码是用C / C ++编写的
  • 如果在指定" --help"时未创建GUI窗口,则将获得加分。 (即,从短暂的窗口中无闪烁)

以我的经验,控制台应用程序的标准Visual Studio模板不具有GUI功能,并且普通的win32模板不会将其stdout发送到父cmd shell。

解决方案

回答

Microsoft将控制台和GUI应用程序设计为互斥的。
这种短视意味着没有完美的解决方案。
最受欢迎的方法是拥有两个可执行文件(例如cscript / wscript,
Java / javaw,devenv.com / devenv.exe等),但我们已表明我们认为此"作弊"。

我们有两种选择来制作"控制台可执行文件"或者" gui可执行文件",
然后使用代码尝试提供其他行为。

  • GUI可执行文件:

" cmd.exe"将假定程序没有控制台I / O,因此不会等待其终止
在继续之前,这在交互模式下(即不是批处理)意味着显示下一个(" C:>""提示符)
和从键盘上读取。因此,即使我们使用AttachConsole,输出也会混合在一起
cmd的输出,如果尝试输入,情况会变得更糟。这基本上是一个入门者。

  • 控制台可执行文件:

与信念相反,没有什么可以阻止控制台可执行文件显示GUI的,但是有两个问题。

首先是如果我们在命令行中不带任何参数运行它(因此需要GUI),
cmd仍将等待其终止后再继续,因此特别
控制台在这段时间内将无法使用。这可以通过启动来克服
同一可执行文件的第二个进程(我们认为这种作弊吗?),
将DETACHED_PROCESS标志传递给CreateProcess()并立即退出。
然后,新进程可以检测到它没有控制台并显示GUI。

下面的C代码说明了这种方法:

#include <stdio.h>
#include <windows.h>

int main(int argc, char *argv[])
{
    if (GetStdHandle(STD_OUTPUT_HANDLE) == 0) // no console, we must be the child process
    {
        MessageBox(0, "Hello GUI world!", "", 0);
    }
    else if (argc > 1) // we have command line args
    {
        printf("Hello console world!\n");
    }
    else // no command line args but a console - launch child process
    {
        DWORD dwCreationFlags = CREATE_DEFAULT_ERROR_MODE | DETACHED_PROCESS;
        STARTUPINFO startinfo;
        PROCESS_INFORMATION procinfo;
        ZeroMemory(&startinfo, sizeof(startinfo));
        startinfo.cb = sizeof(startinfo);
        if (!CreateProcess(NULL, argv[0], NULL, NULL, FALSE, dwCreationFlags, NULL, NULL, &startinfo, &procinfo))
            MessageBox(0, "CreateProcess() failed :(", "", 0);
    }
    exit(0);
}

我用cygwin的gcc YMMV和MSVC编译了它。

第二个问题是,从资源管理器运行时,程序将瞬间
显示控制台窗口。没有解决方案,因为控制台是
Windows在启动应用程序时开始执行之前创建的应用程序。你唯一能做的
要做的是,在安装程序中,使用以下命令的"显示命令"为程序创建快捷方式:
SW_HIDE(即0)。除非我们特意遵守STARTUPINFO的wShowWindow字段,否则这只会影响控制台。
在程序中,所以不要这样做。

我已经通过黑客cygwin的" mkshortcut.exe"进行了测试。你如何完成
它取决于我们选择的安装程序。

用户当然仍然可以通过在资源管理器中找到可执行文件来运行程序。
双击它,绕过控制台隐藏的快捷方式,并看到控制台窗口的短暂黑色闪烁。我们无能为力。

回答

我知道我的答案来晚了,但是我认为在这种情况下,首选的技术是" .com"和" .exe"方法。

根据我们对两个可执行文件的定义,这可能被认为是"作弊",但是程序员几乎不需要任何更改,并且可以一劳永逸。同样,此解决方案也没有Hugh解决方案的缺点,在该解决方案中,我们有一秒钟会显示一个控制台窗口。

在Windows命令行中,如果我们运行程序且未指定扩展名,则在定位可执行文件时的优先顺序将首选.com而不是.exe。

然后,我们可以使用技巧使" .com"成为stdin / stdout / stderr的代理,并启动同名的.exe文件。这提供了一种行为,该行为允许程序在从控制台调用时以命令行模式执行(可能仅在检测到某些命令行参数时才执行),同时仍然可以作为没有控制台的GUI应用程序启动。

有各种各样的文章对此进行了描述,例如"如何使应用程序同时成为GUI和控制台应用程序?"。 (请参见下面链接中的参考)。

我在Google代码上托管了一个名为dualsubsystem的项目,该项目更新了该技术的旧代码专家解决方案,并提供了源代码和有效的示例二进制文件。

希望对我们有所帮助!