【问题标题】:Returning console ownership to parent process将控制台所有权归还给父进程
【发布时间】:2016-12-15 14:21:03
【问题描述】:

是否可以将正在运行的进程与其控制台分离将该控制台的所有权交还给父进程?

也就是说,我希望从cmd.exe 开始的进程将自己与控制台分离(即关闭控制台不会杀死进程)并继续在后台运行,同时控制标准输入、输出和错误流返回给cmd.exe,以便用户可以继续运行命令。

本质上,我正在尝试大致近似在 Linux 上调用 fork 的外观。

我目前正在做:

#include <windows.h>

int main() {
    FreeConsole();
    Sleep(10000);
    return 0;
}

即使控制台窗口关闭,这也会使进程保持活动状态,但标准流的控制权不会交还给cmd.exe,直到睡眠超时并且进程终止。

编辑:该功能是跨平台库的一部分,可以从用户代码中的任意点调用,因此将应用程序重构为更多 Windows-y、调用外部命令、重新启动进程(或启动两步启动序列中另一个父进程的进程)、创建 Windows 服务等不幸的是不是可行的解决方案。

【问题讨论】:

  • 尝试用START /B program运行你的进程
  • 将 CREATE_NEW_CONSOLE 传递给 CreateProcess
  • 我试图实现的fork-ish 函数是库的一部分,几乎可以出现在客户端代码中的任何位置。因此,通过外部命令或CreateProcess 重新启动进程是不可行的。
  • 您可能需要更灵活一些。在 Windows 上实现 fork 是不可行的。
  • 确实它不可行,这就是为什么我试图弄清楚是否有可能近似它的这一特定方面。如果事实证明这是不可能的,那么这也是该问题的有效答案。

标签: c windows winapi console


【解决方案1】:

Windows 没有fork 的概念;它的进程模型与 Linux 非常不同,因此,您应该为这两种操作系统设计不同的应用程序架构。但是,问题中没有足够的信息让我能够建议替代设计。

在您描述的特定情况下,您可能可以通过调用FreeConsole 将控制台窗口与进程分离。现在,问题在于如果控制台不与任何其他进程共享,它会自动销毁。因此,您需要从另一个进程首先调用AttachConsole,以便在两个进程之间共享控制台,然后从其中分离控制台(通过调用FreeConsole)原来的过程。我不知道这是否真的有效;我从来没有尝试过这样的事情。它也没有解决流所有权转移的问题。

如果您希望应用程序有时在控制台窗口中显示输出但不绑定到该控制台窗口(并且可以在后台继续运行),请考虑创建标准 Windows 应用程序而不是控制台应用程序,然后根据需要分配和释放控制台。

【讨论】:

  • 确实,这就是为什么我只是试图近似它的“从控制台分离”方面而不是重新实现它的实际语义,如果 Cygwin 实现可以通过的话,这将是相当麻烦的.如果这是一个独立的应用程序,我肯定会重新设计,但不幸的是这里不是一个选项(请参阅编辑了解更多上下文)。
【解决方案2】:

您的问题是基于误解。 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。

【讨论】:

  • 很好的答案,很好的解决方法建议!根据本答案最后一段的精神,我最终将库的 POSIXy 部分拆分为一个单独的模块层次结构,该层次结构仅在非 Windows 系统上构建。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-02
  • 1970-01-01
  • 2019-04-22
  • 1970-01-01
  • 2013-07-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多