Страница 1 из 2
Как определить, что приложение уже запущено?
Добавлено: 19 июл 2006, 09:38
BBB
Здравствуйте!
Не подскажете, как из Delphi-йной программы можно определить, что другая копия этой программы на данном компьютере уже запущена?
Попытался использовать функция FindWindow (как это делается в "клссических" примерах по Си). Делал вызов этой функции сразу после begin (т.е. даже ДО Application.Initialize), указав в качестве имени класса окна имя формы приложения (здесь трудностей не было, имя класса "подсмотрел" через микрософтовский Spy). Но функция "ответила", что такое окно уже существует! Откуда сделал вывод, что "где-то там, внутри" окно уже существует, и приложение нашло "само себя"...
Заранее спасибо.
Добавлено: 19 июл 2006, 10:26
Duncon
Код: Выделить всё
program Project1;
uses
Forms,
Windows,
Unit1 in 'Unit1.pas' {Form1};
{$R *.RES}
var
hwnd: THandle;
begin
hwnd := FindWindow('TForm1', 'Form1');
if hwnd = 0 then
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end
else
SetForegroundWindow(hwnd)
end.
Добавлено: 19 июл 2006, 10:49
BBB
Duncon, спасибо. Но ты уверен, что ЭТО работает?
Ранее я практически именно так и делаел, лишь вторым параметром в FindWindow передавал NIL (в Си я поступал так же).
Попробовал указывать и второй параметр (как в твоем примере).
Я так понял, что туда ты передавал атрибут
Caption, указанный в свойствах формы (у меня заголовок окна изменен со стандартного - в твоем примере "Form1" на другой - "Кандидаты").
Результат - тот же самый. FindWindow возвращает НЕНУЛЕВОЕ значение.
Пробовал даже вынести вызов FindWindow в отдельный unit, в инициализационную часть и подключить этот Unit в списке uses ДО Forms, предположив, что так проверка вызовется до инициализации unit-а Forms. Но не помогло. Все равно FindWindow что-то находит.

Добавлено: 19 июл 2006, 12:30
Blood_Magic
Duncon писал(а):Код: Выделить всё
program Project1][/quote]
не сработает если резко запустить 2 раза
Добавлено: 19 июл 2006, 13:48
Eugie
Обычно для этой цели используют мьютекс или др.объекты синхронизации.
См. пример:
http://www.akzhan.midi.ru/win32api/26.htm
Добавлено: 19 июл 2006, 15:31
Duncon
Вот еще вариант
Код: Выделить всё
begin
if HPrevInst <>0 then
begin
ActivatePreviousInstance;
Halt;
end;
end;
Или у кого притензии может вам так проще будет....
Код: Выделить всё
unit FirstHinstanceRunning;
interface
uses
Windows,
Forms,
StrUtils,
SysUtils;
function FirstHinstanceRunning(RunMode: Integer = 0): boolean;
implementation
function FirstHinstanceRunning(RunMode: Integer = 0): boolean;
const
MemFileSize = 127;
var
MemHnd: HWND;
MemFileName: string;
lpBaseAddress: ^HWND;
FirstAppHandle: HWND;
begin
Result := False;
MemFileName := Application.ExeName;
case RunMode of
0:
MemFileName := AnsiReplaceText(MemFileName, '\', '/');
1:
MemFileName := ExtractFileName(MemFileName);
else
Exit;
end;
//если FileMapping есть - то происходит OpenFileMapping
MemHnd := CreateFileMapping(HWND($FFFFFFFF), nil,
PAGE_READWRITE, 0, MemFileSize, PChar(MemFileName));
if GetLastError <> ERROR_ALREADY_EXISTS then
begin
if MemHnd <> 0 then
begin
lpBaseAddress := MapViewOfFile(MemHnd, FILE_MAP_WRITE, 0, 0, 0);
if lpBaseAddress <> nil then
lpBaseAddress^ := Application.Handle;
end;
end
else
begin
// MemFileHnd := OpenFileMapping(FILE_MAP_READ, False, PChar(MemFileName));
Result := True;
if MemHnd <> 0 then
begin
lpBaseAddress := MapViewOfFile(MemHnd, FILE_MAP_READ, 0, 0, 0);
if lpBaseAddress <> nil then
begin
FirstAppHandle := lpBaseAddress^;
ShowWindow(FirstAppHandle, SW_restore);
SetForegroundWindow(FirstAppHandle);
end;
end;
end;
if lpBaseAddress <> nil then
UnMapViewOfFile(lpBaseAddress);
end;
В тексте проекта * .dpr вызов функции выглядит приблизительно следующим образом
program OneHinstance;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1},
FirstHinstanceRunning in '..\..\FirstHinstanceRunning.pas';
{$R *.res}
begin
Application.Initialize;
if FirstHinstanceRunning(0) then
Exit;
Application.CreateForm(TForm1, Form1);
Application.Run;
// CloseHandle(MemHnd);
end.
Добавлено: 31 июл 2006, 21:52
psix
Самое простое - CreateMutex() - проверка буквально в одну строчку.
большинство приложений делают именно так.
Добавлено: 01 авг 2006, 08:43
LAngel
FindWindow "всегда" находит окно, только когда приложение запущено в дизайн-тайм (под оболочкой дельфы), потому что в оболочке существует окно с тем же классом и заголовком.
Попробуй закрыть проект и запустить exe, тогда все будет работать как положено

Добавлено: 13 авг 2006, 01:58
corb
У меня такой вопрос - мне надо считать, сколько приложений запущено.
Я вижу вариант c map файлом: создавать его на 4 байта больше и в них записывать 1. В другом экземпляре при открытии мэп-файла, увеличивать счетчик на 1, а при завершении программы его уменьшать.
Вопрос такой: может есть какой-нибудь объект синхронизации, автоматически поддерживающий счет?
Добавлено: 14 авг 2006, 22:06
Eugie
Автоматически счет поддерживают семафоры, но не в том смысле, как надо для ваших целей.
Mapping - неплохой вариант.