PDA

View Full Version : How to know if your app is already running when you start it.



simper66
15th December 2007, 19:27
Hello everyone,

Would somebody know some way of see if your app is already running when you start it and therefore stop the launching?

I work with Qt4.3.2 on XP Sp2.

Thanks a lot ...

marcel
15th December 2007, 20:15
There's a commercial solution for this, from Trolltech: http://trolltech.com/products/qt/addon/solutions/catalog/4/Utilities/qtsingleapplication/.

Otherwise, you have to find platform dependent solutions. For windows you can search codeproject.com and for Mac there are probably solutions on developer.apple.com.

momesana
15th December 2007, 21:34
linux apps often solve this problem by creating a lock file containing the process id of the running application. If another instance of the app is launched it will check if such a lock file exists. if not everything is ok and the app starts and creates its own lock file. If there already exists a pid lock file, the new app extracts the process id from the file and checks whether the app is still running (the pid is still valid). If it is the app will exit, if not the app will start and overwrite the lock file with its own process id. The application should delete their corresponding pid on exit. If it crashes and thus cannot delete the lockfile, this approach still works due to the checking of the state of the pid.

simper66
16th December 2007, 11:33
The "lock file" runs great :D

I was thinking doing something like that but with a socket instead. I think with a file is better.

If somebody is interested I,ve done this in the entry point of the app:



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

Csec csec(argc, argv);

QFile lockFile("lock.dat");
if (lockFile.exists() && !lockFile.remove()) {
QMessageBox::critical("BLA BLA BLA");
return 0;
}
if (!lockFile.open(QIODevice::Truncate | QIODevice::WriteOnly)) {
QMessageBox::critical("BLA BLA BLA");
return 0;
}

MainWindow *mainWindow = new MainWindow;
mainWindow->show();
int rtn = csec.exec();

lockFile.close();

return rtn;
}

ModeZt
16th December 2007, 13:52
QFile lockFile("lock.dat");

Just a note. The better way is to use absolute path to the file. Your app will create a "lock.dat" in the current directory and thus it may be started multiple times from different shourtcuts for example

wysota
16th December 2007, 15:42
With this approach if your application crashes or is killed, you won't be able to restart it. You forgot to implement the second part - checking the pid contained in the file.

ModeZt
16th December 2007, 16:00
With this approach if your application crashes or is killed, you won't be able to restart it. You forgot to implement the second part - checking the pid contained in the file.

This case is covered in
if (lockFile.exists() && !lockFile.remove())
If the one app is running the second app won't be able to remove the lock.
I don't know if holding the open file handler while the app is running is good style but it seems OK for me.

wysota
16th December 2007, 17:04
I don't think this is a foulproof approach... For instance under Windows if an application holding a file open crashes, files opened with mandatory locking (which seems to be the default case on Windows when opening for writing) can't be opened again (or removed) by another process. This is a tricky situation... The best possible solution is to use shared memory or a similar ipc mechanism (sockets are fine too although they trash the system a bit).

simper66
16th December 2007, 17:38
Well, after some time playing with it the method is running OK everytime.


The better way is to use absolute path.................. from different shourtcuts for example
A good appreciation.



....if your application crashes or is killed, you won't be able to restart it.....
I make that test. I aborted the program before close the file and the app could be restarted later. I suppose that the SO itself close the file if the PID is dead.
Anyway, you can know what is your PID with the QProcess::pid() method, but how can you discover what other processes are running in the system?????? I can´t find this functionality anywhere.


Another two observations:

- I edited the piece of code because the line Csec csec(argc, argv); has to be the first line. Otherwise the first "alert" don´t run. I suppose this is because the event loop must be running for dialogs to run.

- In fact, the only one sentence that really do all the work is this:
if (lockFile.exists() && !lockFile.remove())
because if i start the app lots of times this sentence always goes well
if (!lockFile.open(QIODevice::Truncate | QIODevice::WriteOnly))
It seems like lots of processes could open a file in write mode, but fortunately they can´t
delete it if it´s opened by another one.

vcp
17th December 2007, 11:20
Hi,

This is my code (which is similar to the above) and works fine:

In the main.cpp program:


QString arq;
#ifdef Q_OS_WIN32
arq="C:\\windows\\system32\\lock.ctl";
#else
arq="/var/run/lock.ctl";
#endif
QFile dlock(arq);
if(dlock.exists()) {
QMessageBox::critical(mw,"MyApp",
".this programs already is running",
QMessageBox::Close);
QApplication::restoreOverrideCursor();
return -1;
}
else {
dlock.open(QFile::WriteOnly | QFile::Truncate);
QTextStream out(&dlock);
out << "running" << endl;
dlock.close();
}


mw->show();
return app.exec();


In the MainWindow subclass, make follow:

Create a eventClose(QEventClose *event) protected funcion like this.
This funcion will be remove the lock file when the user end the application.


void Compras::closeEvent(QCloseEvent *event)
{
if(!isWindowsActived() ) {
QString arq;
#ifdef Q_OS_WIN32
arq="qcompras.ctl";
QDir d("C:\\windows\\system32\\");
#else
arq="lock.ctl";
QDir d("/var/run/");
#endif
d.remove(arq);
event->accept();
close();
}
else
event->ignore();
}

Fastman
17th December 2007, 11:29
I'am use QtSingleApplication
http://doc.trolltech.com/solutions/4/qtsingleapplication/qtsingleapplication.html

Sample:


int main(int argc, char *argv[])
{
//QApplication::setStyle (new QPlastiqueStyle());
//QApplication a(argc, argv);
QtSingleApplication::setStyle(new QPlastiqueStyle());
QtSingleApplication a("iTMHSM",argc, argv);

if (a.sendMessage("12345"))
return 0;

a.initialize();

HSM w;
w.show();

QObject::connect(&a, SIGNAL(messageReceived(const QString&)),
&w, SLOT(once(const QString&)));
a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));

return a.exec();
}