Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 19.08.2009, 13:37   #1
D_E_N
Форумчанин
 
Регистрация: 04.05.2009
Сообщений: 149
По умолчанию запрет второго такого же процесса

Всем привет! Ребят как сделать чтоб приложение запускалось в единственном экземпляре. Я делал проверку имени и пути к файлу но работало не стабильно. что посоветуете?
D_E_N вне форума Ответить с цитированием
Старый 19.08.2009, 13:45   #2
Volt
Форумчанин
 
Аватар для Volt
 
Регистрация: 07.12.2008
Сообщений: 244
По умолчанию

Код:
program Project1;

uses
  Windows,
  Forms,
  Dialogs,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}
Var HM :THandle;

function Check: boolean;
begin
  HM:=OpenMutex(MUTEX_ALL_ACCESS, false, 'Proj');
  Result:=(HM<>0);
  if HM=0 then HM:=CreateMutex(nil, false, 'Proj');
end;

begin
If Check then
begin
  ShowMessage('Извините, но одна из копий программы уже запущена.');
  exit;
end;
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.
|̲̅̅●̲̅̅|̲̅̅=̲̅̅|̲̅̅●̲̅̅]

Последний раз редактировалось Stilet; 19.08.2009 в 14:50.
Volt вне форума Ответить с цитированием
Старый 19.08.2009, 13:57   #3
artemavd
Старожил
 
Аватар для artemavd
 
Регистрация: 05.06.2008
Сообщений: 4,206
По умолчанию

Или так:
Код:
var
  AtomText: array [0..31] of Char;

procedure LookForPreviousInstance;
var
  PreviousInstanceWindow : hWnd;
  AppName : array[0..30] of char;
  FoundAtom : TAtom;
begin
  // помещаем имя приложения в AtomText
  StrFmt(AtomText, 'OnlyOne%s', [Copy(Application.Title,1,20)]);
  // Проверяем, не создано ли уже атома с таким именем приложения
  FoundAtom := GlobalFindAtom(AtomText);
  if FoundAtom <> 0 then { эта копия приложения уже запущена }
  begin
    StrFmt(AppName,'%s', [Application.Title]);
    // изменяем текущий заголовок, чтобы FindWindow не видела его
    Application.ShowMainForm := false;
    Application.Title := 'destroy me';
    // ищем предыдущую копию приложения
    PreviousInstanceWindow := FindWindow(nil,AppName);
    // Передаём фокус на предыдущую копию приложения
    // завершаем текущую копию
    Application.Terminate;

    if PreviousInstanceWindow <> 0 then
      if IsIconic(PreviousInstanceWindow) then
        ShowWindow(PreviousInstanceWindow,SW_RESTORE)
      else
        SetForegroundWindow(PreviousInstanceWindow);
  end;
  // создаём глобальный атом, чтобы предотвратить
  // запуск другой копии приложения
  FoundAtom := GlobalAddAtom(AtomText);
end;

constructor TForm.Create(AOwner: TComponent);
begin
  inherited;
  LookForPreviousInstance;
end;

destructor TForm.Destroy;
var
  FoundAtom : TAtom;
  ValueReturned : word;
begin
  // не забудьте удалить глобальный атом
  FoundAtom := GlobalFindAtom(AtomText);
  if FoundAtom <> 0 then
    ValueReturned := GlobalDeleteAtom(FoundAtom);
  inherited Destroy;
end;
Не стоит смеяться над человеком делающим шаг назад, возможно он делает разбег.
artemavd вне форума Ответить с цитированием
Старый 19.08.2009, 14:07   #4
D_E_N
Форумчанин
 
Регистрация: 04.05.2009
Сообщений: 149
По умолчанию

Спасибо, попробую.
D_E_N вне форума Ответить с цитированием
Старый 19.08.2009, 23:10   #5
Somebody
Участник клуба
 
Регистрация: 08.10.2007
Сообщений: 1,185
По умолчанию

Атомы, насколько помню, не удаляются из таблицы после некорректного убийства процесса. А теперь насчёт первого примера... Нет ReleaseMutex, да и вторую копию можно запустить, пока первая выполняется между OpenMutex и CreateMutex (то же со вторым примером). Проверять наличие признака уже выполняющейся проги и создавать этот признак, каким бы он ни был, надо обязательно одной операцией. Иначе последствия могут быть очень нехорошие.
Примеры похожих ошибок: Состояние гонки
Мой вариант:
Код:
{$APPTYPE CONSOLE}
uses
  Windows;
var
  h: THandle;
begin
  h := CreateMutex(nil, false, 'ProgramQwertierIsRunning');
  if h = 0 then
  begin
    MessageBox(0, 'Something''s going wrong', nil, MB_ICONERROR);
    halt(0);
  end;
  if not (WaitForSingleObject(h, 0) in [WAIT_OBJECT_0, WAIT_ABANDONED]) then
  begin
    MessageBox(0, 'The program is already running', nil, MB_ICONERROR);
    halt(0);
  end;
  Write('Hi there!');
  ReadLn;
  ReleaseMutex(h);
end.
WAIT_ABANDONED - если предыдущую копию проги завершили ненормально.

Последний раз редактировалось Somebody; 19.08.2009 в 23:16.
Somebody вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Отсортировать матрицу вот такого вида! defol-2009 Общие вопросы C/C++ 2 22.07.2009 13:23
Возможен ли поиск такого вида... littlecoder Общие вопросы Delphi 5 21.12.2008 21:26
Задача такого плана! Dubineanschi Microsoft Office Excel 6 02.09.2008 18:33
Запрет на завершение процесса Черничный Win Api 5 22.07.2008 20:13