Недавно добавленные исходники

•  TDictionary Custom Sort  1 838

•  Fast Watermark Sources  1 870

•  3D Designer  3 289

•  Sik Screen Capture  2 293

•  Patch Maker  2 472

•  Айболит (remote control)  2 294

•  ListBox Drag & Drop  1 891

•  Доска для игры Реверси  69 543

•  Графические эффекты  2 492

•  Рисование по маске  2 026

•  Перетаскивание изображений  1 591

•  Canvas Drawing  1 589

•  Рисование Луны  1 606

•  Поворот изображения  1 224

•  Рисование стержней  1 276

•  Paint on Shape  907

•  Генератор кроссвордов  1 419

•  Головоломка Paletto  1 105

•  Теорема Монжа об окружностях  1 450

•  Пазл Numbrix  1 025

•  Заборы и коммивояжеры  1 301

•  Игра HIP  864

•  Игра Go (Го)  829

•  Симулятор лифта  961

•  Программа укладки плитки  803

•  Генератор лабиринта  963

•  Проверка числового ввода  863

•  HEX View  998

•  Физический маятник  867

•  Задача коммивояжера  918

 
скрыть


Delphi FAQ - Часто задаваемые вопросы

| Базы данных | Графика и Игры | Интернет и Сети | Компоненты и Классы | Мультимедиа |
| ОС и Железо | Программа и Интерфейс | Рабочий стол | Синтаксис | Технологии | Файловая система |



Как не допустить запуск второй копии программы 12



Автор: Тихонов Михаил

Он основан на объекте ядра FileMapping. Такой способ уже был приведен ранее, но в отличие от приведенного, в нем использован оригинальный метод получения дескриптора первого запущенного приложения. Хэндл дескриптора первого запу- щенного приложения (Application.Handle) как раз и сохраняется в области дан- ных объекта FileMapping. Используется только одна функция FirstHinstanceRunning. Она имеет один параметр RunMode, Значения которого должны быть определены следующим образом:

  • если RunMode = 0 то недопущение повторного запуска того-же самого EXE файла с учетом пути
  • если RunMode = 1 то недопущение повторного запуска того-же самого EXE файла без учета пути
  • иначе повторный запуск разрешен

Ниже приводится текст функции:

unit FirstHinstanceRunning;

interface

uses
  Windows,
  Forms,
  StrUtils,
  SysUtils;

function FirstHinstanceRunning(RunMode: Integer = 0): boolean;

implementation

function FirstHinstanceRunning(RunMode: Integer = 0): boolean;
const
  MemFileSize = 127;

var
  MemHnd: HWND;
  MemFileName: string;
  lpBaseAddress: ^HWND;
  FirstAppHandle: HWND;

begin
  Result := False;
  MemFileName := Application.ExeName;
  case RunMode of
    0:
      MemFileName := AnsiReplaceText(MemFileName, '\', '/');
    1:
      MemFileName := ExtractFileName(MemFileName);
  else
    Exit;
  end;
  //если FileMapping есть - то происходит OpenFileMapping
  MemHnd := CreateFileMapping(HWND($FFFFFFFF), nil,
    PAGE_READWRITE, 0, MemFileSize, PChar(MemFileName));
  if GetLastError <> ERROR_ALREADY_EXISTS then
  begin
    if MemHnd <> 0 then
    begin
      lpBaseAddress := MapViewOfFile(MemHnd, FILE_MAP_WRITE, 0, 0, 0);
      if lpBaseAddress <> nil then
        lpBaseAddress^ := Application.Handle;
    end;
  end
  else
  begin
    //    MemFileHnd := OpenFileMapping(FILE_MAP_READ, False, PChar(MemFileName));
    Result := True;
    if MemHnd <> 0 then
    begin
      lpBaseAddress := MapViewOfFile(MemHnd, FILE_MAP_READ, 0, 0, 0);
      if lpBaseAddress <> nil then
      begin
        FirstAppHandle := lpBaseAddress^;
        ShowWindow(FirstAppHandle, SW_restore);
        SetForegroundWindow(FirstAppHandle);
      end;
    end;
  end;
  if lpBaseAddress <> nil then
    UnMapViewOfFile(lpBaseAddress);
end;

В тексте проекта * .dpr вызов функции выглядит приблизительно следующим образом

program OneHinstance;

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

{$R *.res}

begin
  Application.Initialize;

  if FirstHinstanceRunning(0) then
    Exit;

  Application.CreateForm(TForm1, Form1);
  Application.Run;

  //  CloseHandle(MemHnd);      //надо ли ???
end.

Обращаю Ваше внимание на то, что функция CloseHandle() не используется. В качестве обоснования этого привожу две выдержки из литературы:

А вдруг Вы забыли вызвать CloseHandle - будет ли утечка памяти? И да, и нет. Утечка ресурсов (тех же объектов ядра) вполне вероятна, пока процесс еще исполняется. Однако по завершении процесса операционная система гарантированно освобождает все ресурсы, принадлежавшие этому процессу, и в случае объектов ядра действует так: в момент завершения процесса просматривает его таблицу описателей и закрывает любые открытые описатели.

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








Copyright © 2004-2023 "Delphi Sources" by BrokenByte Software. Delphi World FAQ

Группа ВКонтакте   Facebook   Ссылка на Twitter   Ссылка на Telegram