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

  • Автор темы UXr
  • Дата начала
U

UXr

Необходим метод, позволяющий определить программе, что её копия загружена и выполняется.
Если есть какие соображения поделитесь!
 
P

Pasha

Для: UXr
Мьютексы и
 
U

UXr

случай:
программу "насильно" завершает другой процесс, будет ли уничтожен созданный мьютекс?
 
Z

zubr

Для: 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

UXr

случай:
создаётся мьютекс с уникальным именем.
GetLastError возвращает значение <> 0 (мьютекс уже имеется),
но программа на самом деле не запущена. Как избежать такой ситуации?
 
P

Pasha

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

SunSanych

Для 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

UXr

пояснение:
"Программа запущена" - это и значит что она запущена и при этом создала мьютекс.
пояснение к случаю:
какое-то приложение(не наша программа) уже создало мьютекс с именем, которое использует
наша программа.

Может необходим метод динамического формирования уникального имени на основе сис-ых параметров ОС или каких-нибудь других?
Только какие(или какой) лучше использовать?
Или кто предложет более простой но верный метод?
 
U

UXr

Для: SunSanych
// Регистрируем класс окна

программа не имеет окон. Это будет работать?
Но в любом случае я считаю, что для моей программы статическое задание имени (класса окна, мьютекса, что там ещё... атома(где-то встречал) не очень верный способ).
Может у кого есть мысли о варианте наиболее действенного метода определения запущенной копии программы.
(без ложных срабатываний)!
 
Z

zubr

Вариант:
Создаем майлслот (пайп, сокет) на прослушку. При получении определенного сообщения, даем определенный ответ. Прога при открытии посылает сообщение "Я открываюсь", а ей в ответ "Закройся" или ничего.
 
S

SunSanych

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

вы бы уже попробовали что-нибудь, теоретик вы наш
+1
 
U

UXr

Хотелось бы побольше про эти самые майлслот (пайп, сокет) узнать на примере в исходниках.
 
Z

zubr

Вот примеры создания майлслота на прослушку (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

Для: 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

zubr

Для: Pasha
Никто не спорит. Но автора темы вариант с мьютексами не устраивает. У меня к сожалению времени нет проверить версию автора, что при убийстве приложения мьютекс остается.
 
U

UXr

прийдётся делать выбор...
хотелось бы избежать ложных срабатываний, но чем эффективнее, тем сложнее.
При достаточно длинном и "сложном" имени, вероятность наличия такого же
мьютекса, созданного другим приложением мала.
Для моей же программы, в моём случае её использования, думаю, подойдёт вариант с мьютексом.
(И буду надеяться что в ответственный момент она запуститься и не позволит
запуститься копии).

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

Pasha

Для: 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, и посмотри.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!