Логин: Пароль:    Регистрация Всеми возможностями сайта можно пользоваться
только после авторизации.
   Забыли пароль?

Поиск
L



Статистика
u
Пользователи онлайн: нет
Гостей онлайн: 7
Всего онлайн: 7
Зарегистрировано юзеров: 7938
Комментариев на сайте: 698
Новый юзер: Henryfar



Последние комментарии
c
Dennisvoifs прокомментировал "Урок 3 - Конструкция IF...THEN...ELSE":
Пункт коммерческого учета цена, Ктп комплектные трансформаторные подстанции москва, Производство ктп москва и не только Вы найдете на нашем специализированном сайте: - Вам к нам!https://sviloguzov.ru/
Arthurneime прокомментировал "Урок 53 - Потоки в Delphi, (часть 1/3)":
[img]https://masterfutures.ru/wp-content/uploads/2020/03/14-2.png[/img] Online trading is becoming increasingly popular, as more people learn of the earning potential of platforms such as Broker, a broker which caters to a significant audience of digital traders (12 million and counting). Known for their excellent user interface, as well as fast deposit and withdrawal times, Broker provides multiple features to help traders earn on the markets. This overview will outline just some of the key aspects traders can expect to enjoy whilst working with Broker broker. Online trading is becoming increasingly popular, as more people learn of the earning potential of platforms such as Broker, a broker which caters to a significant audience of digital traders (12 million and counting). Known for their excellent user interface, as well as fast deposit and withdrawal times, Broker provides multiple features to help traders earn on the markets. This overview will outline just some of the key aspects traders can expect to enjoy whilst working with Broker broker. Broker Broker is operated by a dedicated team, whose main priority has always been to provide the best possible user experience, and ultimately satisfaction. Whether experienced in trading or a newcomer, the platform is easy to use and very responsive. The education section deserves special mention, particularly for assisting traders to learn and implement new strategies – which can be tested on the platforms free demo Source: [url=https://bit.ly/35fv3B6/]Broker[/url] https://bit.ly/35fv3B6/ Tags: Broker

Ограничение количества одновременно запущенных экземпляров приложения

Обсуждение данной темы ведется, начиная с появления первых 32-х разрядных версий Windows. Казалось бы, проблема давно уже должна быть окончательно решена, но количество вопросов в конференциях и форумах не уменьшается, хотя из книги в книгу, из FAQ'а в FAQ кочуют одни и те же варианты решения. Но не все так очевидно и просто.

Определим требования, которым должно удовлетворять решение для того, что бы его можно было использовать в большинстве случаев. Очевидно, что способ должен:

  • работать во всех версиях ОС;
  • быть надежным;
  • достаточно универсальным;
  • простым в реализации;
  • не давать побочных эффектов.
Каким образом можно поступить? На ум сразу приходит решение «в лоб»: почему бы не просмотреть список всех запущенных в системе процессов и не определить, запущен ли уже наш исполняемый модуль? Но почему-то именно этот «очевидный» способ практически никогда не используется. Для получения списка процессов в Windows 9X используются функции ToolHelp, а в Windows NT – PSAPI. То есть для разных версий Windows и алгоритмы разные. Оставим этот способ для отладочных средств и просмотрщиков…

Довольно распространена проверка на наличие окна с известным заголовком. Способ хорош тем, что если такое окно существует, то оно выводится на передний план. Однако и тут существуют некоторые неприятные особенности, ограничивающие применение способа. А именно, возможна реальная ситуация, когда между процедурой проверки и созданием окна происходит довольно длительная инициализация. Экземпляр приложения, запущенный в этот промежуток времени, не обнаружит окна и запуститься. К сказанному следует добавить, что способ не будет работать в приложениях, меняющих заголовок окна и вообще окон не создающих.

Раз «в лоб» нельзя, то остается стандартный способ – при запуске приложения проверить какой-то уникальный признак и, если он не установлен, то установить, а после завершения работы сбросить. Именно так на практике обычно и поступают. Кандидатов на роль уникального признака довольно много, но не все одинаково пригодны для нашей задачи. Например, не лучшим решением будет использовать глобальные атомы. В случае аварийного завершения приложения, когда явно не вызывается GlobalFreeAtom, они имеют неприятную особенность оставаться в системе до ее перезагрузки. По той же причине абсолютно неприемлемы: создание или попытка открытия какого-либо файла, использование реестра и т.п. Лучшими кандидатами остаются объекты ядра – они просты в использовании, быстры, счетчик ссылок на объект, как правило, декрементируется даже при аварийном завершении процесса. Чаще всего это Mutex и FileMapping.

Типичный код выглядит так:
program MyProgram;
uses
  Windows,
  Forms,
  MyUnit in 'MyUnit.pas' {Form1};

{$R *.RES}

var
  Mutex : THandle;
begin
  Mutex := CreateMutex(nil, False, ‘MyMutex’);
  if Mutex = 0 then
    MessageBox(0,'Невозможно создать мьютекс', 'Ошибка',
      MB_OK or MBICONSTOP)
  else if GetLastError = ERROR_ALREADY_EXISTS then
    MessageBox(0,'Программа уже запущена', 'Ошибка',
      MB_OK or MBICONSTOP)
  else
  begin
    Application.Initialize;  
    Application.CreateForm(TForm1, Form1);
    Application.Run;
    CloseHandle(Mutex);
  end;
end.
В приведенном коде все же есть один дефект. Он никогда не проявится в приложениях типа «Hello World!”, но может привести к очень неприятным последствиям в приложениях серьезных. Я имею в виду инициализацию, которая происходит до процедуры проверки при загрузке модулей. Она так же может занимать достаточно много времени. В этих случаях также возможен запуск нескольких экземпляров приложения, что в некоторых случаях может привести к конфликтам доступа и нехватке ресурсов (из-за чего, собственно говоря, чаще всего проверка и производится). Даже если этого и не произойдет, производится бесполезная работа. Отсюда вывод: процедуру проверки необходимо производить как можно раньше, до начала всех инициализаций, и в случае неудачи немедленно завершать приложение. Для этого помещаем процедуру проверки в отдельный модуль, который указываем в списке используемых проектом модулей ПЕРВЫМ:
program MyProgram;
uses
  OneHinst;  
  Windows,
  Forms,
  MyUnit in 'MyUnit.pas' {Form1};

{$R *.RES}

begin
    Application.Initialize;  
    Application.CreateForm(TForm1, Form1);
    Application.Run;
end.

unit OneHinst;
interface

implementation
uses
  Windows;
var
  Mutex : THandle;
  MutexName : array[0..255] of Char;

function StopLoading : boolean;
var
  L,I : integer;
begin
  // В качестве уникального имени мьютекса используем полный путь
  // к исполняемому файлу приложения
  L := GetModuleFileName(MainInstance,MutexName,SizeOf(MutexName));
  // В имени мьютекса нельзя использовать обратные слэши, поэтому
  // заменяем их на прямые
  for I := 0 to L - 1 do
    if MutexName[I] = '\' then
    begin
      MutexName[I] := '/';
    end;
  Mutex := CreateMutex(nil,false,MutexName);

  Result := (Mutex = 0) or // Если мьютекс не удалось создать
  (GetLastError = ERROR_ALREADY_EXISTS); // Если мьютекс уже существует
end;

procedure ShowErrMsg;
const
  PROGRAM_ALREADY_RUN = 'Невозможно запустить программу';
begin
  MessageBox(0,PROGRAM_ALREADY_RUN,MutexName, MB_ICONSTOP or MB_OK);
end;

initialization
  if StopLoading then
  begin
    ShowErrMsg;
    // Так как никаких инициализаций еще не производилось, то
    // спокойно используем для завершения программы Halt -
    // finalization все равно выполнится
    halt;
  end;
finalization
  if Mutex <> 0 then
    CloseHandle(Mutex);
end.
Напоследок еще пример: как ограничить количество одновременно исполняющихся экземпляров приложения
unit LimHinst;
//****************************************************************************
//
// Author: ©2001 Vladimir G. Yudin aka y-soft
// e-mail: y-soft@mail.ru
//
// Description: Ограничение количества одновременно работающих экземпляров 
// приложения.
//
// Отличие от существующих реализаций:
//
// 1. С целью исключения преждевременных инициализаций проверка
// производится в самом начале загрузки приложения, до загрузки всех модулей
// 2. Исключен возможный конфликт имен, т.к. в качестве уникального имени
// используется полный путь к исполняемому модулю
// 3. Изменением значения HinstLim можно установить любое разрешенное количество
// одновременно запущенных экземпляров приложения
// 4. Изменением WaitPause можно регулировать время ожидания 
// (если установить INFINITE, то получится своеобразный вариант горячего
// резервирования)
//
// Тестировалось в WinME и WinNT 4 SP6A. Ошибки не обнаружены
//
// Usage: модуль необходимо указать ПЕРВЫМ в списке uses файла .DPR проекта
// и установить необходимые значения констант HinstLimit и WaitPause.
//
// Возможные расширения:
//
// 1. Значения HinstLimit и WaitPause хранить в INI-файле или в реестре
// 2. Значение HinstLimit  менять динамически в зависимости от условий
//
// Thanks: Спасибо Юрию Зотову за указание на существование проблемы
//
// Disclaimer: Используйте совершенно свободно на свой страх и риск.
// Автор убедительно просит сообщать ему о найденных ошибках и
// внесенных усовершенствованиях.
// Всякие совпадения идей, наименований функций, процедур, переменных и
// констант считать случайными :)
//
//****************************************************************************
interface

const
   //Установите необходимые значения!!!
  HinstLimit = 1;
  WaitPause = 50;

implementation
uses
  Windows;
var
  Semaphore : THandle;
  SemaphoreName : array[0..255] of Char;
  IncCnt : integer;

function StopLoading : boolean;
var
  L,I : integer;
begin
  // В качестве уникального имени семафора используем полный путь
  // к исполняемому файлу приложения (по определению уникален!!!)
  L := GetModuleFileName(MainInstance,SemaphoreName,SizeOf(SemaphoreName));
  // В имени семафора нельзя использовать обратные слэши, поэтому
  // заменяем их на прямые (или еще на что-нибудь кроме #0)
  for I := 0 to L - 1 do
    if SemaphoreName[I] = '\' then
      SemaphoreName[I] := '/';

  Semaphore := CreateSemaphore(nil,HinstLimit,HinstLimit,SemaphoreName);

  Result := (Semaphore = 0) or // Если семафор не удалось создать
  (WaitForSingleObject(Semaphore,WaitPause) <> WAIT_OBJECT_0); // Если семафор занят
end;

procedure ShowErrMsg;
const
  PROGRAM_ALREADY_RUN = 'Лимит исчерпан';

begin
// Главное окно программы еще не существует, поэтому выводим MessageBox 
// без владельца 
 MessageBox(0, PROGRAM_ALREADY_RUN, SemaphoreName, MB_ICONSTOP or 
MB_OK);
end;

initialization
  IncCnt := 0;
  if StopLoading then
  begin
    ShowErrMsg;
    // Так как никаких инициализаций еще не производилось, то
    // спокойно используем для завершения программы Halt -
    // finalization все равно выполнится
    halt;
  end
  else
    IncCnt := 1;
finalization
  if Semaphore <> 0 then
  begin
    // Обязательно явно освобождаем семафор, т.к.
    // автоматически его счетчик ссылок не переустанавливается
    ReleaseSemaphore(Semaphore, IncCnt, nil);
    // Напоследок во избежание неожиданностей освобождаем дескриптор семафора
    // (так предписывает MSDN)
    CloseHandle(Semaphore);
  end;
end.

Вот и всё, Удачи!

Используйте конвертирование PDF в Excel
Источник: thedelphi.ru
Автор: Савельев Александр
Опубликовано: 22 Ноября 2015
Просмотров:


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