![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Избежать двойной запуск программы. [D6, Win2k]
andrey__ © (2004-10-05 16:21:00)Подскажите как осуществить следующее: Допустьм программа уже запущена и работает, но пользователь по какойто причине запускает повторно эту же программу. Мне надо чтобы второй экземпляр программы не запустился , а допустим показалася (активизировалася)интерфейс первой программы. Т.е. как мне кажется должна быть какая-то проверка при запуске программы на её повторный запуск. Как это сделать.
Ihor Osov'yak (2004-10-08 13:05:00) [1]2 [13] tesseract (08.10.04 10:15)
я "в одном месте проги" не использую. А вот кодированием и проектированием порою приходится заниматься. В том числе и многопоточных приложений. И ни разу не встречал ситуации, когда бы было целесообразным строить классовый нахлабушник над обьектами синхронизаци типа семафоров.
Относительно читабельности. Гораздо проще узнать и сообразить что делает вызов типа CreateSemaphore, WaitForXXX, чем TMySuperPuperSinchroClass by Vasia Pupkin.. Особенно, если методы этого TMySuperPuperSinchroClass по сути есть вызов одной апишной функции. И не следует забывть, что эти WaitForXXX очень подробно документрированы, чего не скажесь об очередном TMySuperPuper...
tesseract (2004-10-08 10:15:00) [2]Ну если ты в одном месте проги используешь то да. А если используешт для синхронизации работы потоков, то лучше классами, оишбок мешьше, тем более и код лучше читаеться и в других проектах используеться.
GanibalLector (2004-10-07 02:39:00) [3]2 Ihor Osov'yak © [10]
М-да...красиво.Взял на вооружение
Ihor Osov'yak (2004-10-07 02:21:00) [4]некий GUID -> текстовое представление некоторого GUID
Ihor Osov'yak (2004-10-07 02:18:00) [5]2 [9] OSokin © (06.10.04 18:55)
Атомы плохо. Почему плохо - вскользь упрминается в сылке постинга [5].
2 [8] tesseract (06.10.04 09:41)
Я вот не понимаю, зачем городить класс, где можно обойтись двумя-тремя апишными вызовами, максимум в пять строчек.
program BlaBla;
uses
windows,
...
{$R *.RES}
var hSemaphore:THandle;
begin
hSemaphore := CreateSemaphore(nil,0,1,'A4EFEC39-D9A3-4F45-A0C5-4B60D811E1EA');
// сигнатура семафора - некий GUID, сгенерированный для даного проекта
try
if GetLastError = ERROR_ALREADY_EXISTS then begin
// инстанция уже запущена,
// здесь обычно код по переводу уже запущеного приложения на передний план
Exit;
end;
Application.Initialize;
Application.CreateForm(...);
Application.Run;
finally
ReleaseSemaphore(hSemaphore,0,nil);
end;
end.
OSokin (2004-10-06 18:55:00) [6]Атомами можно попробовать.
if
GlobalFindAtom('ATOM_FOR_ONCE_COPY_NAME') = 0 then
atom := GlobalAddAtom('ATOM_FOR_ONCE_COPY_NAME')
else сlose;
tesseract (2004-10-06 09:41:00) [7]Пример класса Мютекса
// Сам класс
TMutex = class
protected
FHandle:Thandle;
public
function Acquire(Name: PChar):boolean;
function Release: Boolean;
function Get(TimeOut: Integer): Boolean;
published
destructor Destroy; override;
constructor Create;
end;
constructor TMutex.Create;
begin
inherited Create;
end;
function TMutex.Acquire(Name: PChar):boolean;
begin
FHandle := CreateMutex(nil, false, Name);
if (FHandle = 0) or (FHandle=INVALID_HANDLE_VALUE) then result:=false else result:=true;
// Если Мютекс один нужен просто говорим что нельзя если хочешь потоки синхронизировать то RTFM
if GetLastError=ERROR_ALREADY_EXISTS then result:=false;
end;
// Ожидание освобождения - можешь выбросить
function TMutex.Get(TimeOut: Integer): Boolean;
begin
if Fhandle<>0 then
Result := WaitForSingleObject(FHandle, TimeOut) = WAIT_OBJECT_0
else
result:=true;
end;
// Закрываем мютекс
function TMutex.Release: Boolean;
begin
Result := ReleaseMutex(FHandle);
end;
destructor Tmutex.Destroy;
begin
if FHandle<>0 then Release;
inherited Destroy;
end;
А теперь как юзать, из реально работающего проекта
program cool_server;
uses
Windows,
SysUtils,
forms,
Classes,
uThread in 'uThread.pas',
Shared in 'Shared.pas',
formdll in 'formdll.pas',
Scale_frame in 'Scale_frame.pas' {frScale: TFrame},
settings in 'settings.pas' {fmSettings};
{$R *.res}
var
fmWEight:TfmWeight;
AppMutex:Tmutex;
begin
If not AppMutex.Acquire('sserver') then exit;
ScaleIniFile:=ExtractFilePath(application.ExeName)+'settings.ini';
SetIniFile:=ExtractFilePath(application.ExeName)+'scale.ini';
InitSettings(SetIniFile);
ReadIni(ScaleIniFile);
Addlog('Starting application');
Application.Initialize;
Application.CreateForm(TfmWeight, fmWeight);
Application.CreateForm(TfmSettings, fmSettings);
application.Run;
AppMutex.release;
end.
Ihor Osov'yak (2004-10-05 23:50:00) [8]2 [6] XProger © (05.10.04 22:37)
Не делай так.
Как нужно - уже говорили. см. [5] Amoeba © (05.10.04 16:32).
В дополненее к статье упомяну, что нужно иметь ввиду, что на системе может быть несколько сессих (XP, терминальные сессии на сервере), посему нужно определить, где нужно "единственность" - на уровне сессии, или на уровне системы. Если сессии - это получается по умолчанию. если системы - перед именем именованного обьекта нужно указать префикс 'Global\'
XProger (2004-10-05 22:37:00) [9]
hWnd := FindWindow('TForm', nil);
if hWnd <> 0 then
begin
if IsIconic(hWnd) then
ShowWindow(hWnd, SW_RESTORE);
SetForegroundWindow(hWnd);
Halt;
end;
Amoeba (2004-10-05 16:32:00) [10]Здесь на сайте есть целая статья:
http://www.delphimaster.ru/articles/limit.html
Amoeba (2004-10-05 16:30:00) [11]Для этого в ряде библиотек (к примеру ABF) есть даже компоненты.
Jay (2004-10-05 16:28:00) [12]uses SyncObjs;
var check_event: TEvent;
check_event := TEvent.Create(nil, false, true, 'MYPROGRAM_CHECKEXIST');
if check_event.WaitFor(10) = wrSignaled then
begin
...
end
Алхимик (2004-10-05 16:25:00) [13]Поспрошай Яндекс по ключевым словам "вторая копия".
Кучу вариантов предложит.
Amoeba (2004-10-05 16:24:00) [14]Смотри в FAQ!