Предотвращение повторного запуска программы.

  • Автор темы UXr
  • Дата начала
U
#1
Необходим метод, позволяющий определить программе, что её копия загружена и выполняется.
Если есть какие соображения поделитесь!
 
U
#3
случай:
программу "насильно" завершает другой процесс, будет ли уничтожен созданный мьютекс?
 
Z

zubr

#4
Для: UXr
Смотри в MSDN описание функции CreateMutex.
Use the CloseHandle function to close the handle. The system closes the handle automatically when the process terminates. The mutex object is destroyed when its last handle has been closed.
 
U
#5
случай:
создаётся мьютекс с уникальным именем.
GetLastError возвращает значение <> 0 (мьютекс уже имеется),
но программа на самом деле не запущена. Как избежать такой ситуации?
 
P

Pasha

#6
Для: UXr
Если мьютекс создается (т.е. CreateMutex вернул не NULL), то GetLastError вообще нет смысла вызывать.
 

SunSanych

Well-known member
28.06.2006
71
0
#7
Для Windows приложения можно так:

Код:
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
TCHAR szClassName[] = "MyMegaProgram";

// Преверяем, не было ли это приложение запущено ранее
if( ::FindWindow(szClassName, NULL) )
return FALSE;

// Регистрируем класс окна
wc.lpszClassName = szClassName;
.
.
RegisterClassEx(&wc);
.
.
// и т.д.
}
 
U
#8
пояснение:
"Программа запущена" - это и значит что она запущена и при этом создала мьютекс.
пояснение к случаю:
какое-то приложение(не наша программа) уже создало мьютекс с именем, которое использует
наша программа.

Может необходим метод динамического формирования уникального имени на основе сис-ых параметров ОС или каких-нибудь других?
Только какие(или какой) лучше использовать?
Или кто предложет более простой но верный метод?
 
U
#9
Для: SunSanych
// Регистрируем класс окна
программа не имеет окон. Это будет работать?
Но в любом случае я считаю, что для моей программы статическое задание имени (класса окна, мьютекса, что там ещё... атома(где-то встречал) не очень верный способ).
Может у кого есть мысли о варианте наиболее действенного метода определения запущенной копии программы.
(без ложных срабатываний)!
 
Z
#10
Вариант:
Создаем майлслот (пайп, сокет) на прослушку. При получении определенного сообщения, даем определенный ответ. Прога при открытии посылает сообщение "Я открываюсь", а ей в ответ "Закройся" или ничего.
 

SunSanych

Well-known member
28.06.2006
71
0
#11
Для: UXr
программа не имеет окон. Это будет работать?
Да, будет, лишь бы это было Windows-приложение.
В Windows прежде чем создать любое окно, необходимо зарегистрировать для него так называемый "класс окна", для программиста это значит, что нужно заполнить поля структуры WNDCLASSEX и затем вызвать функцию RegisterClassEx(LPWNDCLASSEX wc) (или RegisterClass(LPWNDCLASS wc), как понятно из названия эта более старая).
Причем класс окна регестрируется в системе и может использоваться любыми запущеными программами для своих целей. Удаляется при выходе из программы в которой был зарегестрирован.

вы бы уже попробовали что-нибудь, теоретик вы наш
+1
 
U
#12
Хотелось бы побольше про эти самые майлслот (пайп, сокет) узнать на примере в исходниках.
 
Z
#13
Вот примеры создания майлслота на прослушку (procedure TMyslotServerThread.Execute;) и записи в майлслот (procedure TMyslotClientThread.Execute;). Примеры на Delphi, но общие принципы одинаковы, суть в использовании API - функций CreateMailslot, CreateFile и WriteFile.
Код:
procedure TMyslotServerThread.Execute;
var
mailslot, nb:cardinal;
buf:PChar;
s:string;
begin
mailslot:=CreateMailslot(PChar('\\.\Mailslot\Myslot'), 100,
MAILSLOT_WAIT_FOREVER, nil);
If mailslot=INVALID_HANDLE_VALUE then
begin
ShowMessage('Error slot');
exit;
end;
buf:=StrAlloc(120);
FillChar(buf^, 120, #0);
While (not Terminated) do
begin
ReadFile(mailslot, buf^, 120, nb, nil);
If nb<>0 then
begin
s:=string(buf);
If s='close' then
break;
FOwner.Spisok.Add(s);
Synchronize(ToSpisok);
end;
FillChar(buf^, 120, #0);
end;
StrDispose(buf);
CloseHandle(mailslot);
end;

procedure TMyslotClientThread.Execute;
var
mailslot, nb:cardinal;
buf:PChar;
i:Integer;
begin
mailslot:=CreateFile(PChar(FAdress), GENERIC_WRITE, FILE_SHARE_READ, nil,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
If mailslot=INVALID_HANDLE_VALUE then
begin
ShowMessage('Error clientslot');
exit;
end;
buf:=StrAlloc(Length(FMsg)+1);
FillChar(buf^, Length(FMsg), #0);
StrPCopy(buf, FMsg);
For i:=1 to FCount do
begin
If Terminated then
break;
WriteFile(mailslot, buf^, Length(FMsg)+1, nb, nil);
Sleep(10);
end;
StrDispose(buf);
CloseHandle(mailslot);
end;
 
P

Pasha

#14
Для: zubr
IMHO через мьютексы будет просто короче:
Код:
HANDLE hnd = CreateMutex(NULL, TRUE, m_pszAppName);
if ( GetLastError() == ERROR_ALREADY_EXISTS && WAIT_ABANDONED != WaitForSingleObject(hnd, 1000))
{
AfxMessageBox("Application already running. ");
return FALSE;
}
(с) не мое
 
Z
#15
Для: Pasha
Никто не спорит. Но автора темы вариант с мьютексами не устраивает. У меня к сожалению времени нет проверить версию автора, что при убийстве приложения мьютекс остается.
 
U
#16
прийдётся делать выбор...
хотелось бы избежать ложных срабатываний, но чем эффективнее, тем сложнее.
При достаточно длинном и "сложном" имени, вероятность наличия такого же
мьютекса, созданного другим приложением мала.
Для моей же программы, в моём случае её использования, думаю, подойдёт вариант с мьютексом.
(И буду надеяться что в ответственный момент она запуститься и не позволит
запуститься копии).

Насколько я понял, прочитав MSDN, при любом способе завершения процесса, все связанные с ним дескрипторы закрываются.
В XP мьютекс, созданный данной программой, при завершении из диспетчера уничтожался, проблем не было,
но как это будет в 98-ой?
 
P

Pasha

#17
Для: zubr
Мьютекс остается, и новый экземпляр приложения дожидается его с результатом WAIT_ABANDONED.
Для: UXr
<!--QuoteBegin-UXr+24:11:2007, 00:00 -->
<span class="vbquote">(UXr @ 24:11:2007, 00:00 )</span><!--QuoteEBegin-->В XP мьютекс, созданный данной программой, при завершении из диспетчера уничтожался, проблем не было,
но как это будет в 98-ой?
[snapback]87189" rel="nofollow" target="_blank[/snapback]​
[/quote] Точно так же. Если хочешь быть уверен в этом, найди старый MSDN, и посмотри.