【问题标题】:Qt: How to get live output of a running QProcessQt:如何获取正在运行的 QProcess 的实时输出
【发布时间】:2016-08-31 17:21:43
【问题描述】:

我必须在 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 完成,这可以正常工作,但在我的情况下,Process 会启动一个自动化界面,该界面应该永久在后台运行。因此,我使用了“readyReadStandardOutput”并将其连接到插槽 CheckOutput()。仅当进程完成时才会调用 CheckOutput()。否则我等不及了。

我在谷歌上搜索了很多关于这个问题的信息,但没有任何效果。我非常确定输出正在缓冲,并且如果进程完成则返回。因此,我在无缓冲模式下启动了进程。我也尝试过转发 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。我认为这是正确的方式。
  • 您正在运行的实际进程(由QProcess 对象管理)可能也在缓冲其标准输出。你确定这没有发生吗?
  • "如果您想要一个报告频率更高的 QProcess,请创建您自己的继承自 QProcess 的流程类。" @maxik
  • 这是一个想法,但如何?我不知道如何停用缓冲,因为 QProcess::Unbuffered 不起作用。而且我不认为 statechanged() 是正确的信号,因为它是为 QCheckBox 制作的。也许 bnaecker 是对的,标准输出被缓冲了。但是如何检查呢?

标签: c++ qt


【解决方案1】:

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

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(等待时栏确实从左向右移动)。
  • 你说得对,就是同步。当您从 GUI 线程运行此代码时,它将冻结。如果信号有效,那么使用它们当然更好......
  • 这仍然无法在可执行文件中工作。但在其他工作中。例如 ping
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-08
  • 1970-01-01
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多