PDA

View Full Version : Question about QPID and QProcess



Naahmi
6th February 2013, 09:37
Hello


I have a small example:

main.cpp



#include <QtCore/QCoreApplication>
#include "process.h"

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Process *proc = new Process;
proc->startProcess();

return a.exec();
}



process.h

#ifndef PROCESS_H
#define PROCESS_H

#include <QProcess>

class Process : public QProcess
{
public:
Process();
void startProcess();
};

#endif // PROCESS_H


process.cpp

#include "process.h"
#include <QDebug>
#include <QDir>
#include <QFileInfo>
#ifdef Q_WS_WIN
#include <windows.h>
#endif

Process::Process()
{

}
void Process::startProcess()
{

#ifdef Q_WS_WIN

qDebug() << "Bin dran!";

QString fileName = "69874.ods";

fileName = QDir::tempPath() + "/" + fileName;
QFileInfo fileInfo(fileName);

this->start(QString("rundll32 url.dll,FileProtocolHandler \"%1\"").arg( fileInfo.absoluteFilePath()));

struct _PROCESS_INFORMATION *procInfo = this->pid();

qDebug() << "PID: " << procInfo->dwProcessId;

#endif

#ifndef Q_WS_WIN

#endif
}


i want to open a document (works fine) and get the process for (in my case) for soffice/excel. But qt returned another pid (i think its the qprocess pid and not soffice).

We have a client-server architecture and i want to write back the file to the server if the editor is closed.

Is there a way to get the PID from the childprocess?

proc->state() returned always is runned.

Santosh Reddy
6th February 2013, 10:11
You need to wait until the process has started. Use this->waitForStarted();, to block until the process starts

Naahmi
6th February 2013, 10:48
Same result wrong pid.



this->start(QString("rundll32 url.dll,FileProtocolHandler \"%1\"").arg( fileInfo.absoluteFilePath()));
this->waitForFinished();
struct _PROCESS_INFORMATION *procInfo = this->pid();
qDebug() << "PID: " << procInfo->dwProcessId;

wysota
6th February 2013, 10:58
Why not use QDesktopServices::openUrl() instead?

Santosh Reddy
6th February 2013, 11:05
Why wait for finished ?

Naahmi
6th February 2013, 11:19
Why not use QDesktopServices::openUrl() instead?

openurl doesn't wait until the editor is closed



We have a client-server architecture and i want to write back the file to the server if the editor is closed.

wysota
6th February 2013, 11:34
openurl doesn't wait until the editor is closed

Ah ok.

I'd suggest using the variant of QProcess::start() that accepts arguments as a separate list of strings. You are trying to quote the filename to compensate for spaces in its path but it won't work because quotes are interpreted by the shell (cmd) which in this case is not used. The docs clearly say start() that you use separates arguments based on spaces. So instead use do this:


start("rundll32", QStringList() << "url.dll,FileProtocolHandler" << fileInfo.absoluteFilePath());

Or with Qt5 and C++11:

start("rundll32", { "url.dll,FileProtocolHandler", fileInfo.absoluteFilePath() });

Naahmi
6th February 2013, 11:45
Ah ok.

I'd suggest using the variant of QProcess::start() that accepts arguments as a separate list of strings. You are trying to quote the filename to compensate for spaces in its path but it won't work because quotes are interpreted by the shell (cmd) which in this case is not used. The docs clearly say start() that you use separates arguments based on spaces. So instead use do this:


start("rundll32", QStringList() << "url.dll,FileProtocolHandler" << fileInfo.absoluteFilePath());

Or with Qt5 and C++11:

start("rundll32", { "url.dll,FileProtocolHandler", fileInfo.absoluteFilePath() });


Thanks for the info but the file opens correct but the pid is wrong and ne process doesn't wait. i have no idea to handle this problem.
I'm using Qt4.



Santosh Reddy
Re: Question about QPID and QProcess

Why wait for finished ?


Sorry copy & paste error i have:



this->start(QString("rundll32 url.dll,FileProtocolHandler \"%1\"").arg( fileInfo.absoluteFilePath()));
this->waitForStarted();
struct _PROCESS_INFORMATION *procInfo = this->pid();
qDebug() << "PID: " << procInfo->dwProcessId;

wysota
6th February 2013, 12:09
Maybe the issue is with how rundll32 works? It probably "forks" (or rather spawns the handling app) and ends its own process thus you get pid of the parent that is already dead.

You can check that by executing your command in cmd. If you get a new prompt immediately then what I said is true. If on the other hand you get new prompt only after you close the handler program then it means run32 doesn't return immediately.

Naahmi
6th February 2013, 14:43
Maybe the issue is with how rundll32 works? It probably "forks" (or rather spawns the handling app) and ends its own process thus you get pid of the parent that is already dead.

You can check that by executing your command in cmd. If you get a new prompt immediately then what I said is true. If on the other hand you get new prompt only after you close the handler program then it means run32 doesn't return immediately.

Can't see a new promt.

wysota
6th February 2013, 14:46
Try running the handler not with QProcess but rather with the system() call. If rundll32 doesn't return immediately, it should do exactly what you want.

Naahmi
6th February 2013, 15:01
Try running the handler not with QProcess but rather with the system() call. If rundll32 doesn't return immediately, it should do exactly what you want.

i have tested:



system("rundll32 url.dll,FileProtocolHandler C:/Users/da/AppData/Local/Temp/70233.ods");
qDebug() << "at the end";


and the display is before the editor is closed. the program doesn't wait :-/

wysota
6th February 2013, 15:46
So rundll32 doesn't wait too and there is no solution for what you want that uses rundll32. When I asked you about an immediate prompt after you run rundll32 I guess we had to misunderstand each other -- if system() behaves the way you describe it then rundll32 must have returned immediately.

Naahmi
6th February 2013, 17:00
Do you have some other ideas?

wysota
6th February 2013, 17:11
First of all tell us why you want to halt your application until the editor is closed.

Naahmi
7th February 2013, 10:35
First of all tell us why you want to halt your application until the editor is closed.

Hi,

Our client-server architecture requires that the client wait until the user is finish with editing the file. After this the server synchronized the local file with the file from the server.

wysota
7th February 2013, 11:51
Maybe it is enough for you to use QFileSystemWatcher to detect changes to the file? Monitoring the editor itself would probably not have worked anyway because if the editor was already open when you tried opening the file, the file might have been loaded into this existing editor instead of launching a new one or a new document might have been created while your editor was open causing a situation that ending work on your file does not close the editor application at all.

If monitoring the file system is not good enough for you then maybe you can have a modal dialog in your app which the user has to close to continue.