是否可以将正在运行的进程从其控制台的和手持有者分离回父进程?
也就是说,我希望从cmd.exe
启动一个进程从控制台分离(即关闭控制台不会终止进程)并继续在后台运行,同时控制标准输入,输出和错误流被传回cmd.exe
,以便用户可以继续运行命令。
从本质上讲,我试图粗略估计在Linux上调用fork
的外观。
我目前正在做:
#include <windows.h>
int main() {
FreeConsole();
Sleep(10000);
return 0;
}
即使控制台窗口关闭,这也会使进程保持活动状态,但是在睡眠超时并且进程终止之前,标准流的控制权不会返回cmd.exe
。
答案 0 :(得分:2)
Windows没有fork
的概念;它的流程模型与Linux非常不同,因此,您应该为两个操作系统设计不同的应用程序体系结构。然而,问题中没有足够的信息可以让我建议替代设计。
在您描述的特定情况下,可能能够通过调用FreeConsole
来从进程中分离控制台窗口。现在,问题在于,如果控制台未与任何其他进程共享,则会自动销毁控制台。因此,您需要先从另一个进程首先调用<{1}} ,以便在两个进程之间共享控制台,然后分离控制台(通过调用{{1来自原始进程。我不知道这是否真的有效;我从未尝试过类似的东西。它也没有解决转移流所有权的问题。
如果您希望某个应用程序有时在控制台窗口中显示输出但未绑定到该控制台窗口(并且可以继续在后台运行),请考虑创建标准Windows应用程序而不是控制台应用程序,然后根据需要分配和释放控制台。
答案 1 :(得分:1)
你的问题是基于一种误解。 Windows没有流所有权或控制台所有权的概念。 (当多个进程在同一个控制台上运行时,控制台输入可能会被送到任何要求它的进程;在大多数情况下,一次只有一个进程在控制台上有一个读取挂起。)
您所观察到的是,默认情况下,cmd.exe
等待控制台应用程序退出。 (运行批处理文件时,它还会等待GUI应用程序退出。)应用程序无法更改此行为。
通常的解决方案是让可执行文件作为子进程启动另一个自身副本(通常使用CREATE_NO_WINDOW
选项)然后退出,这是有效的,因为cmd.exe
只等待它启动的进程退出而不是整个流程树。不幸的是,这种方法通常只有在程序执行的第一件事情时才有用(因为你can't sensibly implement fork in Windows)并且听起来好像不是你的情况。
如果你必须实现这个功能,你可以为程序员提供一个函数来在进程启动时调用,在Windows上重新启动可执行文件然后永远不会返回。在这种情况下,您不会使用CREATE_NO_WINDOW
选项(因为孩子可能希望与控制台通信直到它背景本身)并且在调用FreeConsole()之后您将使用IPC来制作父进程退出。 (如果孩子这样做,它也必须退出。如果父进程被杀死,如果在程序背景本身之前发生这种情况,你可能也想要反转这个逻辑并让孩子死掉。)
就个人而言,我认为跨平台库通常只应尝试实现在所有相关平台上实际有意义的功能。本机Windows应用程序从不以这种方式工作,因此在Windows上运行时担心跨平台应用程序会这样做是没有意义的。 YMMV。