如何在 Qt 中为 Linux 下启动的进程打开控制台 window?

How to open a console window for started process under Linux in Qt?

我使用 QProcess 打开控制台 window 但没有显示 window。

QProcess *process = new QProcess();
process->startDetached(command);

我想打开一个 window 来启动文本模式命令,例如adb -s xxxxx shell 打开 shell window 访问 Android 设备。

我找到关键字 CREATE_NEW_CONSOLE 但我不知道如何使用它。

我找到了解决方案,但我认为这是不好的方法:

QString program = "gnome-terminal";
QStringList arguments = QStringList()<<"-e"<< adbCommand;
process->startDetached(program, arguments);

在 Windows 上,控制台和 GUI 可执行文件在可执行格式级别 上存在区别;当启动控制台可执行文件时,操作系统本身要么回收当前控制台(如果父进程本身已经存在于控制台中),要么为新启动的进程分配一个新控制台。

在Linux上,反而没有这样的区别;系统对终端仿真器(这是常规应用程序)一无所知,当可执行文件启动时,它会从父级继承控制终端(尽管有系统调用会影响它),得到 stdin/stdout/stderr 附加到它(再次,除非执行重定向)并开始做它的事情。 GUI 程序只是不希望通过终端进行交互的程序,"happen" 与 X(或 Wayland)服务器对话,但同样,系统无法知道这一点,这都是约定俗成的。

要解决您的问题:当您从 "GUI" 应用程序直接从 adbQProcess 开始时,子进程会继承您的应用程序具有的任何控制终端;因此,如果您的程序是通过 Qt Creator 启动的,您将在 "Application Output" 窗格中看到它的输出,当您从控制台启动它时,您将能够通过它与 adb 交互,并且等等。

如果你想打开 adb 到一个单独的终端,你必须明确地启动终端模拟器,告诉它依次调用 adb;一旦您知道要启动的终端仿真器是什么,这通常很简单,因为任何值得使用的终端仿真器都将接受 -e program_name arguments 选项(模仿 xterm)。

然而,我们的处境很糟糕,因为在典型的 Linux 时尚中,没有标准的、与桌面无关的方式来了解什么是 "default" 终端模拟器,即使几乎每个DE/panel/whatever 某处有此设置。

寻找这种与桌面无关的东西的地方通常是 freedesktop.org(以前称为 X Desktop Group,因此您会在他们的大部分东西中看到首字母缩写词 XDG),其中有a still unresolved bug from 2015 about this kind of issue1. You can see in this mailing list thread 曾考虑过修复它的方法,但 AFAIK 它刚刚消失。

所以,在我看来你有两个选择:

  • 刚刚启动xterm;它不是特别漂亮,但是没有它就没有图形化的 Linux 安装(即使它不是 "real" xterm,也会有一个恰当命名的符号链接),所以你确定它会起作用。

    QStringList arguments;
    // keep your arguments separated to avoid surprises with escaping
    arguments << "-e" << "adb" << "-s" << "xxxx" << "shell";
    process->startDetached("xterm", arguments);
    
  • 如果你想对你的用户特别友好,你可以让终端模拟器使用一个设置,默认设置为 xterm 以确保一般情况下正常工作。

无论如何,请不要对您的特定 DE 使用的终端模拟器进行硬编码 - 并非每个人都使用 gnome-terminal,许多人甚至都没有安装它。


  1. 这个问题特别是关于 "what should xdg-open do when meeting .desktop (=launcher) files that say "这个程序必须 运行 在一个单独的控制台中”,这几乎就是您要解决的问题。如上所述,几乎任何 DE 都支持此标志,但与桌面无关的 xdg-open 不能,因为无法向当前 DE 询问默认终端是什么。