如何创建执行以下操作的Windows应用程序:
根据我的经验,控制台应用程序的标准visual studio模板没有GUI功能,而普通的win32模板不会将其stdout发送到父cmd shell。
答案 0 :(得分:22)
Microsoft设计的控制台和GUI应用程序是互斥的。 这种短视意味着没有完美的解决方案。 最流行的方法是有两个可执行文件(例如.cscript / wscript, java / javaw,devenv.com / devenv.exe等)但是你已经表明你认为这是“作弊”。
你有两个选择 - 制作“控制台可执行文件”或“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创建,在它开始执行之前。你唯一能做到的 您可以在安装程序中使用“show command”创建程序的快捷方式 SW_HIDE(即0)。除非您刻意遵守STARTUPINFO的wShowWindow字段,否则这只会影响控制台 在你的程序中,所以不要这样做。
我通过黑客攻击cygwin的“mkshortcut.exe”进行了测试。你是如何完成的 它在你选择的安装程序中取决于你。
用户当然可以通过在资源管理器中查找可执行文件来运行程序 双击它,绕过控制台隐藏快捷方式并查看控制台窗口的简短黑色闪烁。你无能为力。
答案 1 :(得分:13)
您可以使用AllocConsole()
WinApi函数为GUI应用程序分配控制台。您还可以尝试使用AttachConsole()
附加到父进程的控制台,如果它已经有一个,这是有意义的。将stdout
和stderr
重定向到此控制台的完整代码将如下所示:
if(AttachConsole(ATTACH_PARENT_PROCESS) || AllocConsole()){
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
}
我在Pidgin来源中找到了这种方法(请参阅pidgin / win32 / winpidgin.c中的WinMain()
)
答案 2 :(得分:4)
我知道我的答案迟到了,但我认为这种情况的首选技术是“.com”和“。exe”方法。
这可能被你的两个可执行文件的定义视为“作弊”,但它对程序员部分的要求很少,可以做一个而忘记了。此解决方案也没有Hugh解决方案的缺点,您可以在一秒钟内显示控制台窗口。
在命令行的Windows中,如果运行程序但未指定扩展名,则查找可执行文件的优先顺序将优先于.com而不是.exe。
然后你可以使用技巧让“.com”成为stdin / stdout / stderr的代理并启动同名的.exe文件。这提供了允许程序在从控制台调用时以命令行模式执行的行为(可能仅在检测到某些命令行args时),同时仍然能够作为没有控制台的GUI应用程序启动。
有各种文章描述如“如何将应用程序同时作为GUI和控制台应用程序?” (参见下面链接中的参考文献)。
我托管了一个名为dualsubsystem on google code的项目,该项目更新了此技术的旧codeguru解决方案,并提供了源代码和工作示例二进制文件。
我希望这有用!