solowey
Гость
|
|
« : 19-02-2009 08:34 » |
|
Всем привет! Я только начинаю изучать Dilphi. Я запускаю программу. При повторном запуске той же программы хочу, чтобы появлялось окно с сообщением - Программа уже запущена. Как это можно релизовать?
|
|
|
Записан
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #1 : 19-02-2009 10:31 » |
|
Примерно так (только тут на C++): if (FindWindow(NULL, PROGRAM_NAME) != NULL) { ShowMessage("Программа уже запущена!"); return 0; }
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Basurman
|
|
« Ответ #2 : 19-02-2009 10:35 » |
|
В Windows API есть функция FindWindow, которая позволяет найти окно по имени класса или заголовку окна. Разжёвывать не буду, лучше сам читай SDK. Оно полезней, и запомнится на дольше.
|
|
|
Записан
|
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
|
« Ответ #3 : 19-02-2009 11:34 » |
|
Эммм... для этого необходимо чтобы имя главного окна программы было однозначным, чего в общем случае гарантировать нельзя.
Гораздо "чище" и сделать это через mutex. Как именно это делается в загадочном языке Dilphi не скажу, но help в помощь.
|
|
|
Записан
|
Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома. "Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash "Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman "All science is either physics or stamp collecting." Ernest Rutherford "Wer will, findet Wege, wer nicht will, findet Gründe."
|
|
|
Антон (LogRus)
|
|
« Ответ #4 : 19-02-2009 11:35 » |
|
а я бы создавал при старте именованный канал, если создать не получилось значит уже запущена
|
|
|
Записан
|
Странно всё это....
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #5 : 19-02-2009 11:52 » |
|
или именованный мутекс, я так сделал и оно давно работает В имя засунуть GUID
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #6 : 19-02-2009 13:24 » |
|
Эммм... для этого необходимо чтобы имя главного окна программы было однозначным, чего в общем случае гарантировать нельзя.
Гораздо "чище" и сделать это через mutex. Как именно это делается в загадочном языке Dilphi не скажу, но help в помощь.
Присоединяюсь, я тоже через именованный мьютекс делал, когда мне нужно было решать такую задачу
|
|
|
Записан
|
|
|
|
zubr
Гость
|
|
« Ответ #7 : 19-02-2009 15:59 » |
|
Джон, в Delphi делается так же как и в VS. API Windows от языка и среды разработки не зависит. Я тоже за мутекс. Еще варианты: event, filemapping, атомы.
|
|
|
Записан
|
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
|
« Ответ #8 : 19-02-2009 16:32 » |
|
Джон, в Delphi делается так же как и в VS. А ну тогда вот так: Определяем два мембера: CSingleLock* m_SI_MyProg; CMutex* m_Mutex_MyProg;
В конструкторе создаём и инициаллизируем объекты: ... m_Mutex_MyProg = new CMutex(FALSE,_T("MyProg_9B764182-8624-4EBF-8C76-066C07E1DB13"),NULL); m_SI_MyProg = new CSingleLock(m_Mutex_MyPro); ...
В стартовую процедуру добавляем проверку: ... if(!m_SI_MyProg->Lock(1)) { TRACE0("Прожка уже запущена один раз. Этого хватит.\n"); return FALSE; }
Не забываем удалить: delete m_SI_MyProg; delete m_Mutex_MyProg;
|
|
|
Записан
|
Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома. "Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash "Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman "All science is either physics or stamp collecting." Ernest Rutherford "Wer will, findet Wege, wer nicht will, findet Gründe."
|
|
|
zubr
Гость
|
|
« Ответ #9 : 19-02-2009 17:11 » |
|
var hMutex: cardinal;
hMutex:=CreateMutex(nil, false, '{CB166DD9-9657-458F-920D-EDD75AF8CF52}'); If GetLastError<>0 then begin CloseHandle(hMutex); ShowMessage('Прога уже запущена!'); exit; end;
CMutex - это уже MFC.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #10 : 19-02-2009 18:42 » |
|
Джон, new даже не надо , мона просто глобальную переменную, которую в InitInstance локнуть нужно (так сразу и определится, что уже есть экземпляр программы)
|
|
« Последнее редактирование: 19-02-2009 18:45 от Алексей1153++ »
|
Записан
|
|
|
|
Basurman
|
|
« Ответ #11 : 19-02-2009 19:32 » |
|
Вариантов много. Но используя FindWindow не по имени, а по классу окна всё-таки делается проще и без лишней загрузки системы. Уж класс окна заранее известен и для окон приложений классы разные. В Delphi искать надо по классу главной формы, вот только при разработке программы надо немного поднапрячься и придумать что нибудь отличающееся от TForm1.
|
|
|
Записан
|
|
|
|
zubr
Гость
|
|
« Ответ #12 : 19-02-2009 20:13 » |
|
А если приложение вообще не имеет окна, да и называть главную форму по типу GUID как-то некошерно... А создание мутекса загрузит систему примерно также, как муравей залезший на спину слона.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #13 : 19-02-2009 20:53 » |
|
А создание мутекса загрузит систему примерно также, как муравей залезший на спину слона.
да и проще во столько же раз Буквально - две строки CMutex g_MyMTX(0,"имя");//глобальная переменная //в инициализации приложения if(!g_MyMTX.Lock())return 0;
|
|
|
Записан
|
|
|
|
zubr
Гость
|
|
« Ответ #14 : 19-02-2009 21:00 » |
|
Алексей1153++, ну это с использованием MFC. В Delphi все таки на API надо делать.
|
|
|
Записан
|
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
|
« Ответ #15 : 20-02-2009 09:39 » |
|
Но используя FindWindow не по имени, а по классу окна всё-таки делается проще и без лишней загрузки системы. Чуть конктретней про загрузку системы мютексом. Чёт первый раз про такое слышу? придумать что нибудь отличающееся от TForm1. Во-во. для окон приложений классы разные Вот два раза запустил одну и туже MFC-шную прожку спай++ показал два разных класса: Afx:00400000:8:00010013:00000000:000203FB Afx:00400000:8:00010013:00000000:002C0375 а это при запущеной второй, запустил параллельно её ещё раз, получил: Afx:00400000:8:00010013:00000000:00010549 Джон, new даже не надо , мона просто глобальную переменную А я ООП больше люблю. зы Забыл написать, собственно говоря, почему я CSingleLock стал использовать. На одной мультипроцной системе у юзверов всё-таки были проблемы при использовании только одного мютекса.
|
|
|
Записан
|
Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома. "Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash "Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman "All science is either physics or stamp collecting." Ernest Rutherford "Wer will, findet Wege, wer nicht will, findet Gründe."
|
|
|
Basurman
|
|
« Ответ #16 : 21-02-2009 10:36 » |
|
Попробую отговориться на всё сразу. А если приложение вообще не имеет окна, да и называть главную форму по типу GUID как-то некошерно... А создание мутекса загрузит систему примерно также, как муравей залезший на спину слона.
Если приложение не имеет окна, это уже другой вариант. Мутекс объект - ресурс системы. А ресурсы системы, мне кажется, лучше поберечь для действительно необходимых случаев. Муравей и слон конечно хорошо, но ведь была ещё и соломинка переломившая спину верблюду. Насчёт названия класса формы - чем TZubrMainForm хуже TForm1? Цитата от Джон: Вот два раза запустил одну и туже MFC-шную прожку спай++ показал два разных класса:". А я пользуясь своим шпаем (в смысле - сам сочинил) для разных экземпляров одной и той-же программы получаю одинаковые имена и атомы классов их окон, а описатели окон, идентификаторы процессов и потоков разные. Ну это всё уже около темы, а по теме: В меню IDE Delphi: Project --> View Source. И файл .dpr калечится примерно следующим образом: program ProjectName; {ProjectName = имя проекта} uses {здесь перечислены используемые модули} {$R *.res} {это от папы Бормана, лучше не трогать} Var CheckHandle : HWND; {добавлены 2 строки - объявление переменной} begin CheckHandle:=FindWindow(MainFormClassName, nil); {найти окно главной формы приложения по классу} If CheckHandle<>0 then {окно найдено, уже запущен экземпляр приложения} begin If IsIconic(CheckHandle) then ShowWindow(CheckHandle, SW_RESTORE); {если окно свёрнуто, восстановить} SetForegroundWindow(CheckHandle); {сделать активным окном переднего плана} {при нужде можно выдать сообщение типа: "Приложение уже запущено"} end else {окно не найдено, можно запускать приложение} begin {Здесь операторы, которые были до изменения} end end
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #17 : 21-02-2009 12:02 » |
|
Basurman, а где ты ещё мутексы часто используешь ? Или другие хендлы ? Думаю, ОДИН хендл на ОДИН экземпляр программы - простоты ради - святое дело.
|
|
|
Записан
|
|
|
|
Basurman
|
|
« Ответ #18 : 21-02-2009 14:28 » |
|
А разве в системе только одна моя программа крутится? Программ то много, и каждая норовит урвать побольше. Вот запустил систему, открыл блокнот - уже 37 процессов запущено, причём половина из них ненужные. Для интереса смотрю на SpeedFan - 21 окно верхнего уровня (top-level), не многовато ли для утилиты контролирующей температуру, частоту вращения вентиляторов и напряжения. Кстати тоже на Delphi VCL сделана, знакомые всё лица - TApplication, TForm1. Раньше на компе стояла система, да видеоредактор. Захват видео шёл на ура, без пропусков кадров. А теперь пропускает только так. Вообще то, это отдельная тема.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #19 : 21-02-2009 14:33 » |
|
Basurman, 37 процессов изза блокнота ? Да у вас, батенька вирусы... У меня - с блокнотом связан всего процесс и один ПОТОК.
Вирусы надо лечить
|
|
|
Записан
|
|
|
|
Basurman
|
|
« Ответ #20 : 21-02-2009 14:41 » |
|
Да нет, не из за блокнота. Acronics (стереть бы его, да лень), Catalyst, да прочая похабщина, такая как - сервис от Canon, сервис от Epson.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #21 : 21-02-2009 14:50 » |
|
Basurman, то есть система то плохо работает вовсе не изза программ, а изза бардака Если я поставлю в автозапуск 1000 безобидных блокнотов, думаю, что система тоже будет тормозить А, заметь, сабж преследует цель не дать запустить более одного экземпляра программы
|
|
|
Записан
|
|
|
|
zubr
Гость
|
|
« Ответ #22 : 21-02-2009 16:15 » |
|
Раньше на компе стояла система, да видеоредактор. Захват видео шёл на ура, без пропусков кадров. А теперь пропускает только так.
У корректно-сделанного видеоредактора такого быть не должно. Если системе не хватает ресурсов, то должно тормозиться видео, но никак не пропуск кадров.
|
|
|
Записан
|
|
|
|
Basurman
|
|
« Ответ #23 : 24-02-2009 18:24 » |
|
О zubr, великий и ужасный, поделись секретом обучения курению видеомагнитофона и телевещания!!! Надо же им чем то заняться, пока комп с захватом тормозит. А вообще ушли от темы. Надо с этим перемещаться.
|
|
|
Записан
|
|
|
|
Kivals
|
|
« Ответ #24 : 24-02-2009 20:19 » |
|
Я тоже за mutex, хотя потом все равно искать окно, чтобы показать запущенный экземпляр. Минус FindWindow: окно создается дольше, потому на загруженной системе если подряд запустить 2 экземпляра приложения, то запустятся оба, т.к. окно не найдет ни одна (пример - WinAmp 2.X: попробуйте на загруженной системе с установленной опцией "только 1 экземпляр" запустить несколько раз). Код для Delphi (вставить в *.dpr): ... const MutexApplicationName = '{Некий GUID}'; var HMutexApplication : THandle; LastErr : DWord;
begin // Это главный begin проекта HMutexApplication := CreateMutex(nil, FALSE, MutexApplicationName); // Неудача при создании - наверное приложение уже запущено if HMutexApplication=0 then begin LastErr := GetLastError; if LastErr=ERROR_ALREADY_EXISTS then begin // Здесь можно найти приложение по окну, но можно и не найти - см. выше Exit; end; end; ... // Все, что было раньше за begin
Для Delphi 5 нужно было в uses включить Windows. Для более поздних - не знаю.
|
|
|
Записан
|
|
|
|
DrGluck
|
|
« Ответ #25 : 12-03-2009 11:55 » |
|
Всю жисть такая задача через мьютекс решалась. Закрывайте тему.
|
|
|
Записан
|
Good user - dead user
|
|
|
|