Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Исключение повторного запуска проги


Автор: TP@MB@Y 25.6.2005, 18:12
У многих прог такая вещь реализована, т.е. нельзя запустить программу несколько раз если она уже запущена. Хочу у своих прог тоже так делать.

Вот что я пытаюсь изобразить:
Код

procedure TfMain.FormCreate(Sender: TObject);
begin
 if findwindow(nil,'Project1.exe')<>0 then close
end;


Но прога всеравно запускается повторно.

Автор: _hunter 25.6.2005, 18:37
а ты уверен что окно именно так называется? запусти WinSight и посмотри

Автор: Poseidon 25.6.2005, 18:51
Код
program Project1;

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

{$R *.res}

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

begin
  if Check then Exit;
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

Автор: Quadr0 25.6.2005, 18:51
...

Автор: Quadr0 25.6.2005, 19:09
...

Автор: Albinos_x 25.6.2005, 19:44
я пользуюсь таким вариантом:

Код

var
  Form1: TForm1;
  CheckEvent:TEvent;
 

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
CheckEvent:=TEvent.Create(nil,false,true,'MYPROGRAM_CHECKEXIST');
IF CheckEvent.WaitFor(10)<>wrSignaled then
   begin
   Application.Terminate;
   end;
end;
...

Автор: jack128_ 26.6.2005, 11:57
Quadr0
Цитата(Quadr0 @ 25.6.2005, 18:51)
begin
  if hPrevInst then
  begin
    ShowMessage('Program is already running!');
    Halt;
  end

Застрял в Win16? ;)
Подъитоживая все предложенные методы: создаешь именнованный объект ядра. Если в процессе создания выледзла ошибка ERROR_ALREADY_EXISTS (объект с заданным именем уже существует) то завершаешь программу. Имя объекта должно быть уникальным, так чтот лудше использовать для именнования guid'ы

Автор: TP@MB@Y 26.6.2005, 21:16
Всем спасибо. Принцип понятен smile

Автор: h2o 2.9.2005, 15:36
Нужно зделать Семафор! Простая структура+делает всё что тебе нужно!
Добавлено @ 15:37
в FormCreate пропиши
Код

CreateSemaphore(nil,0,1,'1C db PackIT!Mon');
        {Cоздаём семафор и проверяем, не возникла ли при этом ошибка.
         Если возникла - значит, такой семафор уже существует, то есть уже есть
         запущенный экземпляр программы.}
     if GetLastError=Error_Already_Exists then
      begin
       MessageDlg('Приложение уже запущено!',mterror, [mbok], 0);
       Application.Terminate;
      end;

Добавлено @ 15:39
'1C db PackIT!Mon' - это любое слово, например название твоей проги. если у тебя несколько прог, вписывай разные слова, а то одна не даст другую запустить!

Автор: offline 2.9.2005, 19:02
Я делаю как сказал Poseidon но еще добавляю сообщение, что программа уже запущена, работает 100%, но есть одна фигня, это то, что управление не передается уже запущенной программе smile Было бы хорошо, показать сообщение, а потом перейти к запущенному экземпляру программы.

Автор: _hunter 2.9.2005, 19:13
для этого можеш посылать ей какое-нить сообщение ( WM_USER + N ) можеш event назначить...

Автор: dvamaster 2.9.2005, 19:39
Есть еще Atom, можно при запуске поги проверять его наличие, затем, если не найден, создавать его, а при выходе убивать!

smile

Автор: Romikgy 5.9.2005, 10:08
Атом можно использовать , только одна трабла, при зависании процесса и последующем его гроханье через таскманагер, процесс более запустить не удастся smile

Автор: dvamaster 6.9.2005, 19:50
Romikgy, ты прав, чего-то я про это не подумал

Автор: Angel_19 22.9.2005, 12:37
В наборе RX есть для этого функция. Работает отлично ...

Автор: EvilsInterrupt 27.8.2007, 17:16
Сегодня столкнулся с тем, что нужно было не просто исключить повторный запуск, а весьма хитро исключить )

Разрабатываю репликатор, он цепляется к промышленному COM-серверу, и ложит в базу данных. Этот репликатор разрешено для запуска в двух экземплярах, но ! , в разных папках. К примеру один репликатор для турбогенератора, а другой для котлоагрегата ! ;)

Из этой ситуации, мне не подошел варинт с глобальным атомом, уж очень много мороки - вдруг юзер вырубиль репликатор через диспетчер задач, значит глобальный атом при запуске надо искать и спрашивать юзера, а первый ли он раз запускает этот репликатор.

Вобщем выставил требования таковыми:

1. Возможность запуска двух экземпляров репликатора, но с разных папок.
2. Из одной папки репликатор можно запустить только и только в одном экземпляре
3. Репликатор не должен зависеть от последствий аварийного выключения через диспетчер задач.


При данных требованиях, остановился на следующем коде, может кому и поможет:

Код

  function  IsApplicationRun : Boolean;
  var
    hMutex        : THandle;
  begin
    Result  := False;
    hMutex := CreateMutex(nil, True,
              PChar(AnsiReplaceText(Application.ExeName,'\','/')));
    if  GetLastError = ERROR_ALREADY_EXISTS then
        Result := True;
  end;


hMutex - несмотря на то что это локальная переменная и казалось мы же теряем значение хэндла. Ну и что я спрошу ))) В конечном итоге, хоть через диспетчер задач, хоть через Application.Terminate хэндлы то убиваются - значит убивается и мьютекс ;)

Думаю, это решит проблемы новичков

Автор: 07pov23 20.1.2009, 17:01
Столкнулся с такой проблемой. Вроде бы программа не запускается дважды. Но! В терминальном режиме ни одна фича приведенная здесь не запускается. Подскажите, пожалуйста, как можно запретить запуск нескольких копий программы в терминальном режиме разными пользователе.
ЗЫ. Еще вопрос хоть не совсем в тему, но все же. Как запускать программу в качестве службы или под системой, т.е. еще до аутентификации пользователя

Автор: dumb 20.1.2009, 19:21
Цитата(07pov23 @  20.1.2009,  17:01 Найти цитируемый пост)
как можно запретить запуск нескольких копий программы в терминальном режиме разными пользователе.

07pov23, берешь любой код с CreateMutex/Event/FileMapping и в имени объекта делаешь префикс 'Global\', т.е. вместо 'MyOwnMutex'(см. 3ий пост) становится 'Global\MyOwnMutex'. единственное, что надо бы проверку версии винды делать, ибо до w2k(вроде) такой префикс недопустим.

Цитата(07pov23 @  20.1.2009,  17:01 Найти цитируемый пост)
ЗЫ. Еще вопрос хоть не совсем в тему, но все же. Как запускать программу в качестве службы или под системой, т.е. еще до аутентификации пользователя 
правила форума прочти. а так, как вариант - http://support.microsoft.com/kb/137890

Автор: 07pov23 21.1.2009, 10:00
Вся проблема в том, что как раз win2k и есть.

Автор: bems 22.1.2009, 17:43
Цитата(dumb @  20.1.2009,  19:21 Найти цитируемый пост)
что надо бы проверку версии винды делать, ибо до w2k(вроде) такой префикс недопустим.

а в Висте в глобал очень мало кого пускают

Автор: bartram 24.1.2009, 15:57
Цитата(07pov23 @  20.1.2009,  19:01 Найти цитируемый пост)
ЗЫ. Еще вопрос хоть не совсем в тему, но все же. Как запускать программу в качестве службы или под системой, т.е. еще до аутентификации пользователя 

Модератор: Пожалуйста, один топик - один вопрос.

 Правила форума: http://forum.vingrad.ru/index.php?act=boardrules

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)