-
Нужно реализовать корректную работу мой программы в случае если при ее запуске обнаружена ранее запущенная копия. В этом случае ранее запущенной копии нужно отправить сообщение на закрытие, а копия запущенная позже должна продолжать работать. Реализую поиск копии через атом, в который вместе с сигнатурой добавляю хендл запущенного приложения. Вторая копия находит сигнатуру, вычленяет хендл и отправляет сообщение wm_close_program, которое программа должна получить и закрыться осободив некие ресурсы.
Делаю так:
const wm_close_program=wm_User+500;
type TForm1 = class(TForm) ... ... private { Private declarations } procedure WM_Close_Program_MSG(Var M : TMessage); message wm_Close_Program; public { Public declarations } end;
.... ....
procedure TForm1.WM_Close_Program_MSG(Var M : TMessage); begin GlobalDeleteAtom(m.WParam); application.Terminate; end;
Суть проблемы в том, что если по хендлу, который я беру из атом отправить WM_CLOSE, то программа прекрасно закрывается, а вот сообщение wm_close_program она почему-то обработать не может. Я что не правильно его принимаю?
-
> а вот сообщение wm_close_program она почему-то обработать > не может.
А если вставить после GlobalDeleteAtom(...) слово Close ?
-
> leonidus (13.01.10 01:06)
> работать. Реализую поиск копии через атом
Плохая идея. Если процесс будет терминирован, то атом будет жить вплоть до логофа.
Лучше взять memory mapped file.
-- Regards, LVT.
-
> leonidus (13.01.10 01:06)
> с сигнатурой добавляю хендл запущенного приложения. Вторая .. > не может. Я что не правильно его принимаю?
Если добавляется Application.Handle, то неправильно.
-- Regards, LVT.
-
Вот так ищу атом:
var P: PChar; i,j: Word; handle:integer; begin GetMem(p, 256); for i := 0 to $FFFF do begin GlobalGetAtomName(i, p, 255); if StrPos(p, PChar('MyProgram_')) <> nil then begin handle:=strtoint( copy(p,ansipos('MyProgram_',p)+10,length(p)) ); PostMessage(handle, wm_Close_Program, i, 0); end; end; FreeMem(p);
Вот так записываю атом: atom:='MyProgram_'+inttostr(application.Handle); GlobalAddAtom(pchar(atom));
application.Handle то что нужно, ведь я могу по этому хендлу отправить wm_Close и программа закроется. на счет того, то атом в это случае будет жить вечно, с чего бы это? я отправляю сообщение PostMessage(handle, wm_Close_Program, i, 0); сожержащие номер найденного атома, а обработчик удалит его: GlobalDeleteAtom(m.WParam);. Другое дело, что обработчик то никак не может получить управление, вот и вопрос, почему?
-
> leonidus (13.01.10 11:04) [4]
> Другое дело, что обработчик то никак не может получить управление, > вот и вопрос, почему?
Form1.Handle <> Application.Handle
И согласен с [2] - атомы не лучший вариант.
-
Ок, пусть будет MMF, но всеравно нужно разобраться с хендлом. Чтоже указывать в виде хендла приложения, чтобы можно было через PostMessage отправить собственное сообщение?
-
> leonidus (13.01.10 11:42) [6]
В твоем варианте речь не о приложении, а об окне. У тебя обработчик в твоем примере принадлежит классу TForm1, значит нужен WND окна, которое является экземпляром класса TForm1.
А зачем посылать сообщение? И еще - а почему закрываем первую программу и оставляем работать вторую копию? (Я наоборот обычно делаю - проверяю, если прога уже запущена, то завершаю работу новой копии программы.)
-
> Чтоже указывать в виде хендла приложения, чтобы можно было > через PostMessage отправить собственное сообщение?
Ну ты же сам сказал
> application.Handle то что нужно, ведь я могу по этому хендлу > отправить
Application.Handle - это хэндл главного окна VCL-приложения. Оно невидимо, потому что его ширина и высота равны 0.
-
Разобрался, большое спасибо!
-
Вот как я решал именно эту же проблему: В главном модуле своего приложения с заголовком "program" перед строкой Application.Initialization вставляю следующий код: var tmpStrList: TStringList; i: Integer; tmpAppName: String; flFound: Boolean; begin tmpStrList := TStringList.Create; try FillApplicationsList(tmpStrList); tmpAppName := ExtractFileName(Application.ExeName); for i := 0 to tmpStrList.Count - 1 do begin if AnsiUpperCase(tmpStrList[i]) = AnsiUpperCase(tmpAppName) then begin MessageDlg('Ця програма вже працює!', mtWarning, [mbOk], 0); Exit; // выход происходит до инициализации приложения end; finally tmpStrList.Free; end; Application.Initialize; Application.CreateForm(TfrmTenderMain, frmTenderMain); Application.Run; end;
|