Qt:如何获取正在运行的QProcess的实时输出

5

我需要在QProcess运行时获取输出,因此我编写了以下代码:

CommandExecutor_C::CommandExecutor_C():
  mProcessStatus(AI_UNKNOWN),
  mOnTdiActiveCallback(),
  mTdiProcess(new QProcess)
{
    connect(mTdiProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(CheckOutput()));
    connect(mTdiProcess, SIGNAL(readyReadStandardError()), this, SLOT(CheckOutput()));
}

void CommandExecutor_C::ExecuteCommand(QString &aCommand)
{
  mTdiProcess->start(aCommand, QProcess::Unbuffered | QProcess::ReadWrite);
  LOGINFO(FB_TDI,"Launch command: " + aCommand.toStdString());
}


void CommandExecutor_C::CheckOutput()
{
    QString StdOut = QString(mTdiProcess->readAllStandardOutput());
    QString StdErr = QString(mTdiProcess->readAllStandardError());

    mProcessStatus = CheckTdiAutomationInterface(StdOut.toStdString(), StdErr.toStdString());

    if(mProcessStatus != AI_UNKNOWN)
    {
      OnTdiActive(mProcessStatus);
    }
}

如果QProcess被完成,那么这将很好运作。但在我的情况下,该过程启动了一个自动化接口,应永久在后台运行。因此,我使用了"readyReadStandardOutput"并将其连接到插槽CheckOutput()。只有当进程已完成时,才会调用CheckOutput()。否则,我将一直等待。
我已经搜索了很多关于这个问题的内容,但没有任何作用。我非常确定输出正在被缓冲,并且只有在进程完成时才返回。因此,我已经在Unbuffered-Mode中启动了该进程。我还尝试转发了mTdiProcess的通道。以下是代码:
void CommandExecutor_C::ExecuteCommand(QString &aCommand)
{
  mTdiProcess->setProcessChannelMode(QProcess::ForwardedChannels);
  mTdiProcess->start(aCommand, QProcess::Unbuffered | QProcess::ReadWrite);
  LOGINFO(FB_TDI,"Launch command: " + aCommand.toStdString());
}

但是什么都没用。我希望你能帮助我。

我正在使用Qt 5.4.2,如果这很重要的话。


也许你应该坚持使用信号stateChanged(),因为根据文档,这种情况下似乎不会触发readyReadStandardOutput()信号。如果你想要一个更频繁报告的QProcess,可以创建一个继承自QProcess的自定义进程类,我认为这是正确的做法。 - maxik
可能你正在运行的实际进程(由QProcess对象管理)也在缓冲其标准输出。你确定这不是发生的情况吗? - bnaecker
如果你想要一个更频繁报告的 QProcess,请创建自己的进程类,该类继承自 QProcess。 - Lehtim
那是个好主意,但怎么做呢?我不知道如何停用缓冲,因为QProcess :: Unbuffered不起作用。而且我认为statechanged()不是正确的信号,因为它是为QCheckBox设计的。也许bnaecker是对的,标准输出被缓冲了。但是如何检查呢? - Lehtim
1个回答

4

我通常会像这样定期检查输出:

bool returnBool = false;
while (returnBool == false)
{
    /*! Wait one second if the process finishes. Then read all output to
     * stdout and stderr and redo. */
    returnBool = process.waitForFinished(1000);
    QString outputStdOut = process.readAllStandardOutput();
    QString outputStdErr = process.readAllStandardError();
}

我尝试过类似的东西,但在我的情况下不起作用。这不是同步的吗?我建议在未接收到任何内容时GUI将会冻结。像我所做的那样使用信号和插槽要好得多,因为我正在使用QProgressDialog(进度条在等待时从左向右移动)。 - Lehtim
您是正确的,这是同步的。如果您从GUI线程运行此代码,它将会冻结。如果信号正常工作,那么使用它们当然更好... - Sebastian
这在可执行文件中仍然无法正常工作。但在其他工作中,比如ping命令,就可以正常运行。 - greendino

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接