如何在崩溃时管理Qt应用程序的单个实例?

时间:2015-02-18 09:34:02

标签: c++ qt

我想将我的应用程序作为单个实例执行,目前我正在使用QSharedMemory并且正常工作。我在Ubuntu 12.04上使用Qt5.2.1。

以下是我的测试代码:

QApplication a(argc, argv);
a.processEvents();

const char* MEM_KEY = "56";
QSharedMemory sharedMem(MEM_KEY);

if( !sharedMem.create( 512, QSharedMemory::ReadWrite) )
{
  QMessageBox msgBox;
  msgBox.setText( QObject::tr("Can't start more than one instance of the application.") );
  msgBox.setIcon( QMessageBox::Critical );
  msgBox.exec();
  exit(0);
}


MainWindow w;
w.show();

int p=0;
//p=p/0; // create exception here

return a.exec();

但是if使应用程序崩溃(如上面的代码所示)。如果我再次启动应用程序,它会显示Can't start more than one instance of the application,这意味着前一个实例即使崩溃也仍然存在。在我的情况下不应该发生这种情况。

如何在这种情况下重启我的应用程序?

修改

实际上我的原始项目包含很多源文件(上面的文件仅用于测试)。我想在我的原始项目上实现它,编辑最少的源文件,如果可能的话,只需编辑main.cpp

2 个答案:

答案 0 :(得分:3)

您可以使用QSetting:

int main(int argc, char *argv[])
{
    QSettings settings;
    QApplication a(argc, argv);

    if(!settings.exitedNormaly()) {
        // In case of crash
    }

    // set the flag to false
    settings.setExitedNormaly(false);

    MainWindow w(&settings);
    w.processArg(argc, argv);
    w.show();

    int result = a.exec();
    settings.setExitedNormaly(result == 0);

    return result;
}

结合您的共享内存,您可以在应用程序崩溃的情况下解锁该块。

答案 1 :(得分:1)

for linux:

// ----------------------------------

QProcess *m_prSystemCall;
m_prSystemCall = new QProcess();

QString Commnd = "pgrep  " + qApp->applicationDisplayName();
m_prSystemCall->start(Commnd);
m_prSystemCall->waitForFinished(8000);
QString output(m_prSystemCall->readAllStandardOutput());
QStringList AppList = output.split("\n", QString::SkipEmptyParts);
qDebug() <<"pgrep out:"<<AppList;
for(int i=0;i<AppList.size()-1;i++)
{
    Commnd = "kill " + AppList.at(i);
    m_prSystemCall->start(Commnd);
    m_prSystemCall->waitForFinished(8000);
}

// --------------------------------------------- ----------

和Windows:

#include <tlhelp32.h>
#include <comdef.h>

QString pName = qApp->applicationDisplayName();
pName += ".exe";
PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);

HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);

if (Process32First(snapshot, &entry) == TRUE)
{
    DWORD myPID =  GetCurrentProcessId();
    while (Process32Next(snapshot, &entry) == TRUE)
    {
        const WCHAR* wc = entry.szExeFile ;
        _bstr_t b(wc);
        const char* c = b;

        if (stricmp(c, pName.toStdString().c_str()) == 0)
        {
            HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID);

            qDebug() <<"myPID: "<< myPID << "entry.th32ProcessID" << entry.th32ProcessID;
            if(myPID != entry.th32ProcessID)
                TerminateProcess(hProcess,0);
            QThread::msleep(10);
            CloseHandle(hProcess);
        }
    }

}

CloseHandle(snapshot);