PDA

View Full Version : QProcess::setWorkingDirectory not functioning properly



hardgeus
4th December 2006, 17:30
I am spawning an external program from my QT4 app as follows:


//Extract working directory for .exe
QFileInfo fileInfo(m_sLaunchFilename);
QString fileName = fileInfo.fileName();

//Manually reconstructing path because fileInfo.absolutePath switches
// direction of slashes, and I'm trying to eliminate possible problems
QString sPath = m_sLaunchFilename.left( m_sLaunchFilename.length() - fileName.length() );

//Need just because it's a required argument
QStringList obList;

//Create process object to launch external .exe
QProcess obProcess;

//Set working directory of .exe to whatever directory it lives in
obProcess.setWorkingDirectory( sPath );
//Retrieve for debugging
sPath = obProcess.workingDirectory();

//Run it!
obProcess.startDetached(m_sLaunchFilename, obList);
qDebug() << "Launching " << m_sLaunchFilename << " in working directory " << sPath;


The output is as follows:

Launching "/code/workingdir//workingdir" in working directory "/code/workingdir//"

I have written a little app specifically to help debug this problem. The code of the app is as follows:


int main( int argc, char* argv[] ) {
QApplication app( argc, argv );


qDebug() << "Current path is " << QDir::currentPath();

FILE *fp = fopen("shawsync.ini", "r" );
if( !fp ) {
QMessageBox::information(NULL, "Error", "Unable to open shawsync.ini!");
printf("Unable to open shawsync.ini\n");
}
else {
QMessageBox::information(NULL, "Success", "Success: opened shawsync.ini!");
fclose(fp);
}
} //main

I put a text file "shawsync.ini" in the directory where I built this program. When I manually run this program from the command line, I get the output:

Current path is "/code/workingdir"

And a messagebox denoting that shawsync.ini was found. When it is launched from my other app using QProcess, the output is:

Current path is "/code/hardupdater"

And a message box denoting that shawsync.ini was not found. I have tested this in both Windows and Linux, and neither one is working. The new process is always started in the directory where I ran the parent process (in this case, /code/hardupdater), and the setWorkingDirectory seems to be ignored.

jpn
4th December 2006, 17:38
Setting the working directory to a instance of QProcess has no effect to QProcess::startDetached() because it is a static method.

hardgeus
4th December 2006, 18:04
Setting the working directory to a instance of QProcess has no effect to QProcess::startDetached() because it is a static method.

I didn't notice that it was static because I was calling calling it with an object, but you're right, it is documented as static. Now the question becomes: Is it possible to set the working directory for a detached process? My app is launching the external program on exit so I have to detach it. If I don't detach it, the child process is killed with my app.

hardgeus
4th December 2006, 18:13
Got it. I'm now manually using QDir to set the current working directory before calling startDetached, and then setting it back:


QString sOldPath = QDir::currentPath();
QDir::setCurrent( sPath );

//Run it!
obProcess.startDetached(m_sLaunchFilename, obList);
qDebug() << "Launching " << m_sLaunchFilename << " in working directory " << sPath;

QDir::setCurrent( sOldPath );

pethead
14th February 2018, 13:25
Right way


QProcess process;
process.setProgram(file);
process.setArgument(args);
process.setWorkingDirectory(dir);
process.startDetached();

d_stranz
14th February 2018, 17:03
No, wrong way.

As was stated earlier, QProcess::startDetached() is a static class method and therefore changes made to a specific QProcess instance (like setting the working directory, etc.) have no effect on the detached process. Static class methods, whether you call them using process.startDetached() or QProcess::startDetached() have no access to non-static member variables of a particular instance.

In Qt5, there is a version of QProcess::startDetached() that has arguments to provide the working directory in which the process will be started. That is the "right way".