Russian Qt Forum

Программирование => С/C++ => Тема начата: gil9red от Август 19, 2012, 01:19



Название: [РЕШЕНО] Запуск одной копии программы + Показ первой копии
Отправлено: gil9red от Август 19, 2012, 01:19
Здравствуйте!
Как сделать так что при повторном запуске ехе программы, не создавался новый процесс, а
1-ая копия показывалась юзеру?

Нашел пример похожего: http://www.prog.org.ru/topic_2630_0.html

есть у меня программа, при запуске, показывается сплеш-скрин, потом программа видна в трее, и хочется чтобы при повторном запуске, окно программы показывалось

выглядит main так:
Код:
#include <QtGui/QApplication>
#include <windows.h>
#include "UManager.h"

int main(int argc, char *argv[])
{
    HANDLE mutex;
    LPCWSTR mtxname = L"Mutex";
    if(OpenMutex(MUTEX_ALL_ACCESS, false, mtxname) != 0)
    {
        return -1;
    }else
    {
        mutex = CreateMutex(0, false, mtxname);
    }

    QApplication a(argc, argv);

    QPixmap *pixmap = new QPixmap(":/images/splash.png");

    QSplashScreen *splash = new QSplashScreen(*pixmap);
    splash->show();

    a.processEvents();

    splash->showMessage("initialization...", Qt::AlignRight);

    UManager *manager = new UManager();

    splash->finish(manager);

    delete pixmap;
    delete splash;

    a.setQuitOnLastWindowClosed(false);

    ReleaseMutex(mutex);

    return a.exec();
}


Название: Re: Запуск одной копии программы + Показ первой копии
Отправлено: kambala от Август 19, 2012, 02:00
раз используется Qt, то можно воспользоваться QtSingleApplication


Название: Re: Запуск одной копии программы + Показ первой копии
Отправлено: gil9red от Август 19, 2012, 02:02
Если я не ошибаюсь это сторонняя библиотека и ее нужно скачивать?
Кроме того, хоть и использую Qt, но не скоро моя программа будет на ос кроме винды - пришлось достаточно много использовать винапи, и посмотрев на форуме про QtSingleApplication, понял что с ним слишком много геммороя, и для моего случая проще и удобнее использовать винапишные методы :)


Название: Re: Запуск одной копии программы + Показ первой копии
Отправлено: Bepec от Август 19, 2012, 10:12
Ну тогда вин апи тебе в руки.
1) Получаешь список процессов, сравниваешь названия, если есть - получаешь его id и показываешь
2) в момент запуска 1 программы создаёшь скрытый файл аля - я уже запущена, мой id = *******.
3) использовать sharedMemory вроде - кто-то говорил, с ними тоже можно, но тут уж за что купил - за то и продаю.


Название: Re: Запуск одной копии программы + Показ первой копии
Отправлено: Igors от Август 19, 2012, 11:30
есть у меня программа, при запуске, показывается сплеш-скрин, потом программа видна в трее, и хочется чтобы при повторном запуске, окно программы показывалось
Ну и действуйте в WinAPI если так хочется
Код
C++ (Qt)
   ...
   if(OpenMutex(MUTEX_ALL_ACCESS, false, mtxname) != 0)
   {
       HWND wnd = FindWindow(mtClass, myTitle);
       if (myWnd) {
         if (IsIconic(wnd)) ShowWindow(wnd, SW_RESTORE):
         SetForegroundWindow(wnd);  
       }
       return -1;
   }
   ...
 


Название: Re: Запуск одной копии программы + Показ первой копии
Отправлено: gil9red от Август 19, 2012, 15:37
Igors, винапишная функция поиск окна вряд ли сможет прокатить :(, ведь у меня не одно название окна, которое нужно показать - программа мультиязычная, и заголовок тоже меняется
кроме того, после проверки выяснилось, что чтобы окно первой копии показалось, сначало его нужно показать ("вытащить из трея"), а потом снова спрятать и тогда ваш код работает, но содержимое окна не обновляется оконным менеджером, там всякий мусор отпечатавшийся с фона
Может pipe сообщения прокатят...

в notepad++ реализовано, то что я спрашивал, при запуске второй копии, вторая игнорируется и показывается первая


Название: Re: Запуск одной копии программы + Показ первой копии
Отправлено: LisandreL от Август 19, 2012, 15:52
Может pipe сообщения прокатят...
А pipe в Qt - это QLocalSocket.
А через QLocalSocket реализован QtSingleApplication.
Ну вы понимаете, к чему я клоню (https://github.com/opencor/opencor/tree/master/src/3rdparty/QtSingleApplication/src) ;)


Название: Re: Запуск одной копии программы + Показ первой копии
Отправлено: gil9red от Август 19, 2012, 16:22
Угу :'(


Название: Re: Запуск одной копии программы + Показ первой копии
Отправлено: kambala от Август 19, 2012, 17:23
с QtSingleApplication никаких проблем под виндой нету, разве что при компиляции через студию (по крайней мере 2010) придётся пару файлов не добавлять в проект (я боролся с этим тут (http://www.prog.org.ru/index.php?topic=18874.msg147743#msg147743)).


Название: Re: Запуск одной копии программы + Показ первой копии
Отправлено: Igors от Август 19, 2012, 17:53
Igors, винапишная функция поиск окна вряд ли сможет прокатить :(, ведь у меня не одно название окна, которое нужно показать - программа мультиязычная, и заголовок тоже меняется
кроме того, после проверки выяснилось, что чтобы окно первой копии показалось, сначало его нужно показать ("вытащить из трея"), а потом снова спрятать и тогда ваш код работает, но содержимое окна не обновляется оконным менеджером, там всякий мусор отпечатавшийся с фона
Может pipe сообщения прокатят...
Не знаю, у меня все работает (Win XP 64), правда приложение не использует Qt. Можно попробовать RedrawWindow - а проще не упираться и задействовать QtSingleApplication


Название: Re: Запуск одной копии программы + Показ первой копии
Отправлено: gil9red от Август 30, 2012, 23:19
Вот я и вернулся :)
потерпел фиаско, пытался провернуть с pipe и винапи, но компилятор оказался упрямее меня и не захотел компилить, в итоге удалил нафиг в корзину :D

решил попробовать как и советовали более опытные люди qtsingleapplication :)
скачал заголовочные и исходники для него, добавил в проект, немного изменил main как в примере, при компиляции сборки Отладка, все ок, все работает, при релизе появляется ошибка Microsoft Visual C++ Runtime и в консоле вывода приложения сообщение о не совпадении версий библиотек Qt:
Cannot mix incompatible Qt library (version 0x40801) with this library (version 0x40800)

Разве либы qtsingleapplication не используют либы qt, установленного у меня?
откуда эта ошибка?
как с ней справиться?

Не, конечно, можно и дебаг оставить, но вряд ли кому то понравится качать непонятные dll, весящие в 150раз больше самого ехе ;D


Название: Re: Запуск одной копии программы + Показ первой копии
Отправлено: kambala от Август 31, 2012, 00:07
создай пустой проект и проверь будет ли в нём работать qtsingleapplication


Название: Re: Запуск одной копии программы + Показ первой копии
Отправлено: gil9red от Август 31, 2012, 00:39
Сделал, при отладке все прекрасно работает

в pro файле есть нетворк:
QT += core gui network

main:
Код:
#include "qtsingleapplication/qtsingleapplication.h"
#include <QWidget>

int main(int argc, char **argv)
{
    QtSingleApplication instance(argc, argv);
    if(instance.sendMessage("Wake up!"))
        if(instance.isRunning())
            return 0;

    QWidget w;

    instance.setActivationWindow(&w);
    
    w.show();

    QObject::connect(&instance, SIGNAL(messageReceived(const QString&)),
             &w, SLOT(setWindowTitle(QString&)));

    return instance.exec();
}

могу скинуть этот проект, но проблема похоже у меня


Название: Re: Запуск одной копии программы + Показ первой копии
Отправлено: kambala от Август 31, 2012, 00:46
а проекты без QtSingleApplication нормально работают в релизе я так понимаю? может в PATH есть что-то с устаревшими библиотеками (подозреваю, что проблема в QtNetwork4.dll)?


Название: Re: Запуск одной копии программы + Показ первой копии
Отправлено: gil9red от Август 31, 2012, 00:53
Да, до qtsingleapplication все проекты компилировались без проблем и в релизе, и в отладке
У меня в PATH был путь к папке minGW к dll, но я оттуда сейчас убрал/сохранил, не помогло
может нужно ребутнуть комп?


Название: Re: Запуск одной копии программы + Показ первой копии
Отправлено: kambala от Август 31, 2012, 01:02
minGW тут не при чём, ребут не нужен. чтоб наверняка: помести QTDIR\bin самым первым в PATH


Название: Re: Запуск одной копии программы + Показ первой копии
Отправлено: gil9red от Август 31, 2012, 01:18
Решение было, блин, простым...
забыл что при установке выбрал 2 версии qt 4.8.0 и 4.8.1, и нужно было только выбрать сборку 4.8.0 для qtsingleapplication :)

Но есть еще вопросы, в программе использую QApplication:: и иногда qApp,
1 теперь места с QApplication:: нужно заменить на QtSingleApplication::?
2 а макрос qApp тоже самое что QApplication?
3 qApp можно заменить на QtSingleApplication?
4 QtSingleApplication требует дополнительную dll?
5 есть ли какие то серьезные или не очень баги с QtSingleApplication?
6 QtSingleApplication - бесплатная либа?


Название: Re: Запуск одной копии программы + Показ первой копии
Отправлено: kambala от Август 31, 2012, 01:29
1. нет
2. это макрос для QApplication::instance()
3. зачем?
4. нет
5. вроде нет
6. да


Название: Re: Запуск одной копии программы + Показ первой копии
Отправлено: gil9red от Август 31, 2012, 01:36
Странно...у меня иногда с QtSingleApplication открывается новые копии
при постоянном запускании ехе (раз 10 открывал), это нормально?


Название: Re: Запуск одной копии программы + Показ первой копии
Отправлено: gil9red от Август 31, 2012, 01:39
main таков:
Код:
#include <QtGui/QApplication>
#include "ManagerNote.h"
#include "qtsingleapplication/qtsingleapplication.h"

int main(int argc, char *argv[])
{
    QtSingleApplication instance(argc, argv);
    if (instance.sendMessage("Wake up!"))
        if(instance.isRunning())
            return 0;

    QPixmap *pixmap = new QPixmap(":/images/splash.png");

    pixmap->scaledToWidth(200, Qt::SmoothTransformation);

    QSplashScreen *splash = new QSplashScreen(*pixmap);
    splash->show();

//    instance.processEvents();

    splash->showMessage("initialization...", Qt::AlignRight);

    ManagerNote *managerNote = new ManagerNote();   

    instance.setActivationWindow(managerNote);

    splash->finish(managerNote);

    delete pixmap;
    delete splash;

    instance.setQuitOnLastWindowClosed(false);

    QObject::connect(&instance, SIGNAL(messageReceived(QString)),
                     managerNote, SLOT(messageToApp(QString)));

    return instance.exec();
}

может я что то в main напутал?


Название: Re: Запуск одной копии программы + Показ первой копии
Отправлено: Serr500 от Август 31, 2012, 09:24
Может, надо наоборот?
Код:
QtSingleApplication instance(argc, argv);
if (instance.isRunning()) {
    instance.sendMessage("Wake up!");
    return 0;
}


Название: Re: Запуск одной копии программы + Показ первой копии
Отправлено: gil9red от Август 31, 2012, 10:19
Тьфу, точно :D


Название: Re: Запуск одной копии программы + Показ первой копии
Отправлено: kambala от Август 31, 2012, 10:56
вообще-то sendMessage() возвращает тру если сообщение доставлено существующей копии и фолс в ином случае, так что isRunning() можно и не вызывать


Название: Re: Запуск одной копии программы + Показ первой копии
Отправлено: gil9red от Август 31, 2012, 11:29
но и от такой проверки хуже не станет) и нагляднее выглядит:
Код:
if (instance.isRunning()) // если копия уже запущена, тогда...
{       
    instance.sendMessage("Wake up!"); // отсылаем ей сообщение
    return 0; // закрываемся
}