[英]Ways to execute system commands in qt program without opening console window
[英]How to conditionally enable console without opening separate console window
我想创建一个 windows 应用程序,在正常情况下,它没有任何连接的终端,但在某些情况下可能有一个。 我尝试了两条不同的路线。 选项 A,创建一个普通的控制台应用程序,并有条件地调用FreeConsole()
:
int main()
{
if (someCondition) {
HANDLE stdOutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
WriteConsoleA(stdOutHandle, "hello world\n", 12, NULL, NULL);
} else {
FreeConsole();
// normal operation
}
return 0;
}
和选项 B,创建一个基于 WinMain 的应用程序,并有条件地调用AllocConsole()
。
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nCmdShow)
{
if (someCondition) {
AllocConsole();
HANDLE stdOutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
WriteConsoleA(stdOutHandle, "hello world\n", 12, NULL, NULL);
}
else {
// normal operation
}
return 0;
}
选项 A 的问题在于,它与 windows 应用程序的行为不完全相同,因为您可以在正常操作继续之前非常短暂地看到控制台 window 打开。 这不是一个大问题,但正如我所说,我更希望程序像普通的 windows 应用程序一样运行。
选项 B 的问题在于,如果从现有终端调用程序,它会打开一个单独的终端 window 并输出到该终端,而不是输出到调用它的终端。 这是一个更大的问题。
在没有上述任何一个问题的情况下,有条件地充当控制台程序或 windows 程序的适当解决方案是什么?
编辑
根据评论中的建议,我尝试使用AttachConsole
function。
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nCmdShow)
{
if (someCondition) {
AttachConsole(ATTACH_PARENT_PROCESS);
HANDLE stdOutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
Sleep(3000);
WriteConsoleA(stdOutHandle, "hello world\n", 12, NULL, NULL);
FreeConsole();
}
else {
// normal operation
}
return 0;
}
这似乎是在正确的轨道上,但仍然缺少一些东西,因为我的 shell 提示立即打印出来,而不是等待程序完成。
不可能的。
AttachConsole
不能 100% 工作,因为 cmd.exe 实际上会检查它即将启动的进程是否是 GUI 应用程序,并改变其行为。
使其工作的唯一方法是拥有两个程序; myapp.com 和 myapp.exe。 %PathExt% lists.com before.exe 这样您就可以制作一个console.exe 并重命名它。com 如果用户运行“myapp”,它将被执行(但如果用户键入“myapp.exe”则不会工作)。 如果您的程序不是很大,您可以只发布两个版本。 如果程序很大,您可以将大部分代码移动到 a.dll 或使 .com 成为一个小助手,它使用命令行参数和一些用于 stdin/stdout 的管道调用 the.exe。 Visual Studio 执行此操作 ( devenv.com )。
如果要检查是否已经存在控制台,请检查GetConsoleWindow()
返回的 NULL 。 如果返回 null,则执行 AllocConsole 程序和其他设置(SetWindowLong、SetConsoleMode 等)
int main() 程序默认情况下不会创建控制台,如果通过 cmd/ps 运行,它们碰巧附加到控制台中。
一种方法如下:
BOOL WINAPI
AttachOrCreateConsole()
{
if(AttachConsole(ATTACH_PARENT_PROCESS))
{
return TRUE;
}
return AllocConsole();
}
如果可用,这将使用父控制台,并在需要时回退到创建一个。
请注意,如果您这样做并且想要使用标准 C/C++ I/O 机制(stdin/std::cin、stdout/std::cout),您将需要完成将这些流关联到控制台句柄所需的工作. 有很多关于如何做到这一点的材料。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.