delphi: как проверить, запущено ли приложение и закрыть дубликат экземпляра? [Дубликат]

Я исправил эту проблему с помощью:

  varchar (200)  

заменен на

  varchar (191)   

все varchar, которые имеют более 200, заменяют их 191 или устанавливают их текст.

27
задан Toby Allen 22 January 2013 в 01:41
поделиться

12 ответов

Вы можете создать Семафор и прекратить выполнение (поместите код в ваш файл * .dpr) и принесите запущенное приложение на экран.

var
  Semafor: THandle;

begin
  { Don't start twice ... if already running bring this instance to front }
  Semafor := CreateSemaphore(nil, 0, 1, 'MY_APPLICATION_IS_RUNNING');
  if ((Semafor <> 0) and { application is already running }
     (GetLastError = ERROR_ALREADY_EXISTS)) then 
  begin
    RestoreWindow('TMyApplication');
    CloseHandle(Semafor);
    Halt;
  end;

  Application.CreateForm(....);    
  Application.Initialize;
  Application.Run;
  CloseHandle(Semafor);
end;

EDIT (добавлен метод RestoreWindow). :

aFormName - это имя вашего основного класса формы в вашем приложении.

procedure RestoreWindow(aFormName: string);
var
  Wnd,
  App: HWND;    
begin
  Wnd := FindWindow(PChar(aFormName), nil);
  if (Wnd <> 0) then 
  begin { Set Window to foreground }
    App := GetWindowLong(Wnd, GWL_HWNDPARENT);
    if IsIconic(App) then 
      ShowWindow(App, SW_RESTORE);

    SetForegroundwindow(App);
  end;
end;
17
ответ дан kobik 17 August 2018 в 09:09
поделиться
  • 1
    это greate, но я не могу получить & quot; Восстановить окно ('MyApplication') & quot; работать я должен реализовать это или мне нужно использовать блок, который я в настоящее время не использую – Arthur 20 January 2009 в 21:23
  • 2
    считывание по "процедуре RestoreWindow (WinHandle: HWND); & quot; поскольку мне нужен дескриптор aplicaton, который запускался сначала, мне нужно получить дескриптор приложения, который имеет удержание на семафоре. не уверен, что это новый вопрос или расширение – Arthur 20 January 2009 в 21:53
  • 3
    Ups ... забыл добавить метод RestoreWindow, ... отредактирует ответ – Drejc 20 January 2009 в 21:57
  • 4
    Не знаю, если я получаю форму Name неправильно, но она не открывает старый экземпляр. – Arthur 21 January 2009 в 02:08
  • 5
    Я думаю, что у нас есть случай ползучести. Вы много обитаете в части RestoreWindow ответа. Если вы хотите получить более подробную информацию об этом, я советую вам найти или задать другой вопрос: «Как сделать один экземпляр моей программы активировать другой?». – Rob Kennedy 21 January 2009 в 21:33

В прошлом я использовал сокет для одновременного запуска нескольких экземпляров. Если сокет используется, не продолжайте программу, если она доступна, пусть все работает как обычно.

-1
ответ дан ahanson 17 August 2018 в 09:09
поделиться

Я хотел бы добавить один пункт к превосходному ответу Роба Кеннеди (кроме того, что было бы лучше сделать функцию из своего кода, а не копировать все в DPR файл. Вам нужны только два параметра, имя мьютекса и логическое значение, должно ли mutext быть для каждого пользователя или общесистемного).

В ответе не уделяется много внимания наименованию мьютекс. Если вы ожидаете, что ваша программа будет установлена ​​через Inno Setup (и, возможно, другие инструменты настройки тоже), вы должны тщательно выбрать имя, так как мьютекс можно использовать, чтобы программа установки проверяла, запущена ли в данный момент приложение, и предупредите пользователя, что они должны закрыть все экземпляры приложения. Если вы решите разрешить один экземпляр программы на пользователя, вам может понадобиться создать второй общесистемный мьютекс, так как для установки файлов может потребоваться отсутствие запущенных экземпляров приложения. Имя, которое должно использоваться для синхронизации с установщиком InnoSetup, должно быть жестко запрограммировано.

2
ответ дан Community 17 August 2018 в 09:09
поделиться

Вы можете просто использовать функцию api для окна FindWindow. В классе delphi имя окна совпадает с именем класса, вы можете переопределить имя класса, переопределив функцию CreateParams. Чтобы проверить, существует ли окно, добавить код до создания основного окна, перед Application.Initialize;

Program test
var 
  handle :HWND;
begin
  handle := FindWindow('TMySuperApp', nil);

  if IsWindow(handle) then
  begin 
       //app is running
       exit;
  end.

  Application.Initialize;
  Application.CreateForm(TMySuperApp, SuperApp);
  Application.Run;
end;
1
ответ дан Edin Omeragic 17 August 2018 в 09:09
поделиться
  • 1
    Какие единицы это использование HWND и findwindow не были распознаны. также будет работать, если мое "окно" скрыт в icontray? – Arthur 20 January 2009 в 04:19
  • 2
    Это потребует «Windows». Это полезное дополнение к Mutex, поскольку вы можете перенести предыдущее окно на передний план. Но если пользователь дважды откроет ваше приложение, первый, возможно, еще не открыл его окно, и поэтому он может быть пропущен. – mj2008 20 January 2009 в 10:36

Управление количеством экземпляров приложения:

http://delphi.about.com/od/windowsshellapi/l/aa100703a.htm

1
ответ дан g2mk 17 August 2018 в 09:09
поделиться

См. этот блок (с помощью CreateMutex): UiApp

Кроме того, на этой странице вы можете прочитать преимущества и недостатки этой работы с различными методами (mutex, FindWindows, ...).

У этого устройства есть решение активировать предыдущий экземпляр приложения, когда оно обнаружено.

С уважением и извини меня за мой плохой английский.


Neftalí -Germán Estévez -

0
ответ дан Germán Estévez -Neftalí- 17 August 2018 в 09:09
поделиться

Я бы сказал, что есть несколько различных стратегий, которые вы можете использовать. Но самый простой (а не специфичный для платформы) - это тот, который вы сами предложили, а именно: в начале проверки программы проверьте, есть ли файл блокировки, созданный в наборе, конкретное местоположение. Если этот файл блокировки существует, то другой экземпляр уже запущен, если он не существует, то нет другого экземпляра. Когда ваша программа выходит, вы удаляете файл блокировки.

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

Другая стратегия - это общесистемное решение мьютекса, в котором вы регистрируете свое присутствие в операционной системе (или это также правдоподобно, что это сделано автомагически). Когда второй экземпляр пытается запустить, он проверяет, есть ли уже активный процесс с определенным идентификатором. Если он уже существует, второй процесс выбирает не запускать и, при необходимости, фокусирует первое окно процесса (если рассматриваемый процесс владеет окном).

Однако эта стратегия является специфичной для платформы , и реализация будет отличаться от платформы к платформе.

1
ответ дан jimka 17 August 2018 в 09:09
поделиться

Обычным решением является создание именованного общесистемного мьютекса.

  • Если вам удастся его создать, вы используете одно приложение.
  • Если вы этого не сделаете, вы знаете, что есть другой.

EDIT:

Я не предоставил код как я не знаю Дельфи. Я могу предоставить код C #, если бы это было бы полезно.

38
ответ дан menjaraz 17 August 2018 в 09:09
поделиться
  • 1
    У вас там есть гонка. Всегда вызывайте CreateMutex, а не OpenMutex. Затем используйте GetLastError, чтобы узнать, кто выиграл гонку. – Rob Kennedy 20 January 2009 в 00:21
  • 2
    @Rob Кеннеди, ты прав. Код не смог запустить два экземпляра программы, которые были запущены почти мгновенно. Ваше предложение верное. – Kluge 20 January 2009 в 00:42
  • 3
    Вам нужно закрыть ручку мьютекса, когда приложение выходит? – Sam 20 January 2009 в 05:54
  • 4
    Нет, поскольку мьютекс, как и все другие ресурсы ОС, освобождается / освобождается / независимо от того, когда процесс владения завершается. Это также большой плюс этого решения по сравнению с временными файлами, которые все еще могут существовать после сбоя приложения. – mghie 20 January 2009 в 08:43
  • 5
    Очень рекомендую добавить «Global \\» к имени мьютекса, чтобы мьютекс был охвачен глобально. Если вы входите в качестве другого сеанса или запускаете приложение как служебные мьютексы, которые не являются глобальными, могут быть созданы в отдельных не сталкивающихся пространствах имен. – Einstein 20 January 2009 в 09:33
  • 6
    Эйнштейн, да, глобальный мьютекс хорош, если этого хочет Артур. Однако, исходя из одного из его предыдущих вопросов, я не думаю, что это так. И, как я помню, pre-Win2k не разрешал обратную косую черту в имени, поэтому вы не можете постоянно использовать одно и то же имя. – Rob Kennedy 20 January 2009 в 16:16
  • 7
    Сэм, ОС сделает это за вас. Но вы можете закрыть его раньше. Если текущий экземпляр закрывается, он не сможет принимать сообщения из другого экземпляра. В этот момент может быть лучше для "новых" экземпляр, чтобы принять на себя роль «& quot; экземпляр и только что покинул первый экземпляр. – Rob Kennedy 20 January 2009 в 16:19
  • 8
    этот ответ следует удалить. – Rigel 28 July 2017 в 15:09
17
ответ дан utku_karatas 17 August 2018 в 09:09
поделиться
38
ответ дан menjaraz 6 September 2018 в 06:51
поделиться
0
ответ дан Hamo Redone 29 October 2018 в 13:34
поделиться
38
ответ дан menjaraz 29 October 2018 в 13:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: