PDA

View Full Version : How to use QProcess to write multiple commands to external console based program.



eeghem
2nd June 2010, 10:22
Hi,

I'm using Qt to run inkscape.exe in shell mode. The idea is to process multiple files through inkscape. In shell mode, inkscape accepts commands from stdin. However I'm experiencing problems when I try to write more than one command to inkscape. Here's my code.



int main(int argc, char* argv[]) {
// create application
QCoreApplication app(argc, argv);
QTextStream out(stdout, QIODevice::Unbuffered | QIODevice::WriteOnly);
QProcess inkex;

QStringList arguments;
QString os_program = QDir::toNativeSeparators ("E:/_Inkscape/inkscape.exe");
arguments << "--shell" << "--without-gui";

// start the program
inkex.setProcessChannelMode(QProcess::ForwardedCha nnels);
inkex.start (os_program, arguments, QIODevice::ReadWrite | QIODevice::Unbuffered);
inkex.waitForStarted();

// query the version
inkex.write("--version\n");

// export a file to png
QString svgfile=QDir::toNativeSeparators("E:/_Development/Cpp/RxBuilder/test/test_twee.svg");
QString pngfile=QDir::toNativeSeparators("E:/_Development/Cpp/RxBuilder/test/test_twee.png");
QString cmd="--file=\"%1\" --export-png=\"%2\" --export-area=0:0:1042:768\n";
cmd=cmd.arg(svgfile).arg(pngfile);
out << "---" << endl;
out << cmd << endl;
out << "---" << endl;
inkex.write(cmd.toAscii());

// quit the program
inkex.write("quit\n");
inkex.waitForBytesWritten();
inkex.waitForFinished();

// exit
app.quit();
return 0;
}


The expected result is that the version is displayed and an png-image is created based on the svg-image. However that line never is executed. When the application exits only the version is displayed.

The commandline is not the problem. If I strip the call to:


inkex.write("--version\n");


Inkscape suddenly responds by generating the image. Somehow the first command is actually blocking the execution of the second command. Any idea's on whats wrong here?

Thx.
Ruud

Fraz
13th September 2011, 10:22
I have the same problem. I want to disable network and then enable it.

ifconfig ethPCI down
ifconfig ethPCI up
Here is my code:


QStringList args;
args<<"ethPCI"<<"down";
QProcess *proc = new QProcess();
process->start("ifconfig",args);
process->waitForFinished();
args<<"ethPCI"<<"up";
process->start("ifconfig",args);

For some reason only the first command is executed which disables the interface. Second command is not executing.
If I move the second command up then it works but I have to disable the network before enabling it otherwise its no use for me.

Thanks for any help on this.

wysota
13th September 2011, 10:26
You are not clearing "args" prior to executing line #6.

Fraz
13th September 2011, 11:10
You are not clearing "args" prior to executing line #6.

Thanks I did that and I think now the second command is also executing but now I have another problem. My program is unable to detect that the network is up until I rerun the program. Any ideas about it ?

wysota
13th September 2011, 11:24
How are you detecting the network?

Fraz
13th September 2011, 11:43
How are you detecting the network?
The network is detected by the API provided by my GiGE Camera.
The code for detecting Camera is executed after I run these shell commands. The code before these shell commands is only to initialize the QT GUI.
After some experimentation I have also discovered that if I execute "ifconfig ethPCI down" using QProcess only then Camera / Network is not detected in the same session.
If I rerun the program or check it outside the application camera is accessible without any problems.

wysota
13th September 2011, 11:47
Ok, but probably it takes some time for your system to bring the connection up. The fact that "ifconfig" returns doesn't mean the network is ready for use. If you perform the check immediately after running the commands, you are creating a race condition. Why don't you use Bearer Management API available in Qt Mobility to detect connection changes?

Fraz
13th September 2011, 13:15
Ok, but probably it takes some time for your system to bring the connection up. The fact that "ifconfig" returns doesn't mean the network is ready for use. If you perform the check immediately after running the commands, you are creating a race condition. Why don't you use Bearer Management API available in Qt Mobility to detect connection changes?
OK I did not know about this API, I will give it a go and see if it solves the problem. Thanks :)

Added after 1 21 minutes:


Ok, but probably it takes some time for your system to bring the connection up. The fact that "ifconfig" returns doesn't mean the network is ready for use. If you perform the check immediately after running the commands, you are creating a race condition. Why don't you use Bearer Management API available in Qt Mobility to detect connection changes?

I tried to use Qt Mobility but in my scenario it is useless. The reason I need to disable and enable network interface is that my network card sometimes (randomly) gets disabled by my Linux (Slackware 13.37) kernel.
I tried to resolve that issue at Linux forums but as it seems its a bug in Slackware release or with my card driver. Anyway the only workaround is to disable and enable the card that makes it reusable without restarting the system.
I tried doing the same thing with Qt API but it seems it can not disable the interface. It gives error "The requested operation is not supported by the system"

Anyway! You were spot on ... it was a race condition because it takes some time for the network interface to become available, so I forced it to delay (sleep(5)) for 5 seconds and it solved my problem. Thanks once again. :)