Форум: "WinAPI";
Текущий архив: 2004.11.21;
Скачать: [xml.tar.bz2];
ВнизИзбежать двойной запуск программы. Найти похожие ветки
← →
andrey__ (2004-10-05 16:21) [0]Подскажите как осуществить следующее: Допустьм программа уже запущена и работает, но пользователь по какойто причине запускает повторно эту же программу. Мне надо чтобы второй экземпляр программы не запустился , а допустим показалася (активизировалася)интерфейс первой программы. Т.е. как мне кажется должна быть какая-то проверка при запуске программы на её повторный запуск. Как это сделать.
← →
Amoeba © (2004-10-05 16:24) [1]Смотри в FAQ!
← →
Алхимик © (2004-10-05 16:25) [2]Поспрошай Яндекс по ключевым словам "вторая копия".
Кучу вариантов предложит.
← →
Jay (2004-10-05 16:28) [3]uses SyncObjs;
var check_event: TEvent;
check_event := TEvent.Create(nil, false, true, "MYPROGRAM_CHECKEXIST");
if check_event.WaitFor(10) = wrSignaled then
begin
...
end
← →
Amoeba © (2004-10-05 16:30) [4]Для этого в ряде библиотек (к примеру ABF) есть даже компоненты.
← →
Amoeba © (2004-10-05 16:32) [5]Здесь на сайте есть целая статья:
http://www.delphimaster.ru/articles/limit.html
← →
XProger © (2004-10-05 22:37) [6]
hWnd := FindWindow("TForm", nil);
if hWnd <> 0 then
begin
if IsIconic(hWnd) then
ShowWindow(hWnd, SW_RESTORE);
SetForegroundWindow(hWnd);
Halt;
end;
← →
Ihor Osov'yak © (2004-10-05 23:50) [7]2 [6] XProger © (05.10.04 22:37)
Не делай так.
Как нужно - уже говорили. см. [5] Amoeba © (05.10.04 16:32).
В дополненее к статье упомяну, что нужно иметь ввиду, что на системе может быть несколько сессих (XP, терминальные сессии на сервере), посему нужно определить, где нужно "единственность" - на уровне сессии, или на уровне системы. Если сессии - это получается по умолчанию. если системы - перед именем именованного обьекта нужно указать префикс "Global\"
← →
tesseract (2004-10-06 09:41) [8]Пример класса Мютекса
// Сам класс
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.
← →
OSokin © (2004-10-06 18:55) [9]Атомами можно попробовать.
if
GlobalFindAtom("ATOM_FOR_ONCE_COPY_NAME") = 0 then
atom := GlobalAddAtom("ATOM_FOR_ONCE_COPY_NAME")
else сlose;
← →
Ihor Osov'yak © (2004-10-07 02:18) [10]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.
← →
Ihor Osov'yak © (2004-10-07 02:21) [11]некий GUID -> текстовое представление некоторого GUID
← →
GanibalLector © (2004-10-07 02:39) [12]2 Ihor Osov"yak © [10]
М-да...красиво.Взял на вооружение
← →
tesseract (2004-10-08 10:15) [13]Ну если ты в одном месте проги используешь то да. А если используешт для синхронизации работы потоков, то лучше классами, оишбок мешьше, тем более и код лучше читаеться и в других проектах используеться.
← →
Ihor Osov'yak © (2004-10-08 13:05) [14]2 [13] tesseract (08.10.04 10:15)
я "в одном месте проги" не использую. А вот кодированием и проектированием порою приходится заниматься. В том числе и многопоточных приложений. И ни разу не встречал ситуации, когда бы было целесообразным строить классовый нахлабушник над обьектами синхронизаци типа семафоров.
Относительно читабельности. Гораздо проще узнать и сообразить что делает вызов типа CreateSemaphore, WaitForXXX, чем TMySuperPuperSinchroClass by Vasia Pupkin.. Особенно, если методы этого TMySuperPuperSinchroClass по сути есть вызов одной апишной функции. И не следует забывть, что эти WaitForXXX очень подробно документрированы, чего не скажесь об очередном TMySuperPuper...
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2004.11.21;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.038 c