PDA

View Full Version : QProcess and capturing output



Aragorn
25th April 2007, 04:31
Hello,

I am relatively new to Qt, but so far I am enjoying it! I only hope someone has an idea what may be going wrong with my program...

I am using QProcess to start a process and capture its output. I am running WIN32 console applications, and in some cases, it works fine. For example, I can capture output from ipconfig, or ping, or whatever other command similar to those that I may want to capture.

The issue that I am having right now, however, is that not all programs are capable of being captured. I have access to another binary that if I execute by itself, I get output like I normally would. I can redirect it to a file using typical command line switches (> in this case)... but if I execute it using my program, it exits with a NormalStatus but with a Failed to Start code (added an if statement to check it in the ProcessedFinished function, not shown below), without any output. Several other binaries are the same way...

I have verified that it is not a permission issue, or a path issue for that matter. It isn't failing to start the process, it is producing the failed to start QProcess code in the ProcessFinished funtion but not before.

I don't know where to go from here, as I don't see anyone else having this problem if I search on the web. I am hoping someone here may be able to assist.

The section of code that I am having an issue with is below:


FlashDialog::FlashDialog(QWidget *parent):QDialog(parent)
{
setupUi(this);
connect(okButton,SIGNAL(clicked()),this,SLOT(close ()));
connect(&proc,SIGNAL(readyReadStandardOutput()),this,SLOT(r eadFromStdout()));
connect(&proc,SIGNAL(readyReadStandardError()),this,SLOT(re adFromStdErr()));
connect(&proc,SIGNAL(error(QProcess::ProcessError)),this,SL OT(processError(QProcess::ProcessError)));
connect(&proc,SIGNAL(finished(int,QProcess::ExitStatus)),th is,SLOT(processFinished(int,QProcess::ExitStatus)) );

}
void FlashDialog::setFilePath(QString filePath)
{
proc.start(filePath);
}

void FlashDialog::readFromStdout()
{
QByteArray newData=proc.readAllStandardOutput();
QString text=statusView->toPlainText() + QString::fromLocal8Bit(newData);
statusView->setPlainText(text);

}
void FlashDialog::readFromStdErr()
{
QByteArray newData=proc.readAllStandardError();
QString text=statusView->toPlainText() + QString::fromLocal8Bit(newData);
statusView->setPlainText(text);

}

void FlashDialog::processFinished(int exitCode,QProcess::ExitStatus exitStatus)
{
if(exitStatus==QProcess::CrashExit)
{
statusView->append("Program Crashed";);
}
}

void FlashDialog::enableOkButton()
{

}
void FlashDialog::processError(QProcess::ProcessError error)
{
if(error==QProcess::FailedToStart)
{
statusView->append("Failed to start";);
}
}

I am under somewhat of a time crunch, so any suggestions or help are greatly appreciated!

jacek
25th April 2007, 13:46
Are you sure that these are Win32 binaries? Also check whether they don't require some DLLs.

bitChanger
25th April 2007, 14:23
You might want to open the binaries in dependency walker to verify they are not corrupt, and to verify that they have all of the needed dependencies.



http://www.dependencywalker.com

Aragorn
2nd May 2007, 18:48
The binaries work fine, and are WIN32. They don't depend on anything as they execute on their own without issue.

I have found that if I add 'cmd /c' to the front of them, they seem to work better, however one of them doesn't produce any output until the end of the process. Is there any way to flush QProcess so I can capture the output before the process ends?

marcel
2nd May 2007, 19:07
You could start the process with arguments and redirect its output to a file. Something like "program.exe > proc_out.txt".

This works when using the command line, so it should work fine with QProcess ( it uses CreateProcessW on Windows ).

Regards

Aragorn
2nd May 2007, 21:10
I thought about that too, but I don't think I'll be able to do what I want to do putting it into a file.

Ultimately I want to provide a real-time status of the output of the executable that is being run using QProcess. This is the only executable I am having issues with (and unfortunately, one of the key executables I need to get a status from).

If I try redirecting the output to a file in a command-line window (execute.exe > test.txt) I appear to only get text in it at the end as well... but if I don't redirect it, I get output as I should.

I am guessing I am fighting with this executable, and likely there isn't a way for me to work around it, but before I give up, I want to make sure that there isn't something else that I can do to.

Thanks for everyone's suggestions by the way!

bst
3rd May 2007, 09:15
Hi,

redirection is normally handled inside a shell, not in an external program.

cu, Bernd
--
redir.cpp:


#include <QDebug>
#include <QProcess>

int main(void)
{
QProcess qp1, qp2;

// does not work, because i/o redirection is handled by a shell, not by QProcess or the external exe
// here the string "> c:\\out1" (!) is passed as an argument to argecho
qp1.start("c:\\uti\\argecho.exe", QStringList() << "> c:\\out1" << "1" << "2" << "3");
qp1.waitForFinished();
qDebug() << "qp1:" << qp1.readAll();

// this works (put the redirection before the external command!)
qp2.start("c:\\windows\\system32\\cmd.exe", QStringList() << "/C" << "> c:\\out2" << "c:\\uti\\argecho.exe" << "1" << "2" << "3");
qp2.waitForFinished();
qDebug() << "qp2:" << qp2.readAll();

return 0;
}

argecho.c:


#include <stdio.h>

int main ( int argc, char ** argv )
{
int i;

for ( i = 0; i < argc; i++ )
printf( "%d: %s\n", i, argv[i] );

return 0;
}

Aragorn
3rd May 2007, 16:57
Thank you for the code, however I need to capture the output in real-time. The output appears on the screen in real time, and this is the only executable I am having problems with, so I know the concept of what I am trying to do works.

Does QProcess wait for a certain character, like a new line escape character, before it acknowledges there is content to be read?