Чтение онлайн

на главную

Жанры

О чём не пишут в книгах по Delphi

Григорьев Антон Борисович

Шрифт:

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

то она подключается к нему как клиент и передает содержимое своей командной строки и завершает работу. Сервером в таком случае становится экземпляр приложения, запустившийся первым, — он-то и создаёт почтовый ящик. Остальным экземплярам останется только передать ему данные.

Примечание

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

Почтовый ящик лучше создать как можно раньше, поэтому мы будем его создавать не в методе формы, а в основном коде проекта, который обычно программист не исправляет. В результате код в dpr-файле проекта будет выглядеть так, как показано в листинге 1.48.

Листинг 1.48 Создание почтового ящика в главном файле проекта

const

 MailslotName = '\\.\mailslot\DelphiKingomSample_Viewer_FileCommand';

 EventName = 'DelphiKingdomSamplе_Viewer_Command_Event';

var

 ClientMailslotHandle: THandle;

 Letter: string;

 OpenForView: Boolean;

 BytesWritten: DWORD;

begin

 // Пытаемся создать почтовый ящик

 ServerMailslotHandle := CreateMailSlot(MailslotName, 0,

MAILSLOT_WAIT_FOREVER, nil);

 if ServerMailslotHandle = INVALID_HANDLE_VALUE then

 begin

if GetLastError = ERROR_ALREADY_EXISTS then

begin

// Если такой ящик уже есть, подключаемся к нему, как клиент

ClientMailslotHandle := CreateFile(MailslotName, GENERIC_WRITE,

FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

// В зависимости от того, какие переданы параметры, формируем

// строку для передачи предыдущему экземпляру. Первый символ

// строки - команда:

// e - открыть файл для редактирования

// v — открыть файл для просмотра

// s — просто активизировать предыдущий экземпляр

// Для команд e и v к строке, начиная со 2-го символа,

// добавляется имя файла

if ParamCount > 0 then

begin

OpenForView := (ParamCount > 1) and

(CompareText(ParamStr(2), '/v') = 0);

if OpenForView then Letter := 'v' + ParamStr(1)

elsе Letter := 'e' + ParamStr(1);

end

else Letter := 's';

//
Отправляем команду в почтовый ящик

WriteFile(ClientMailslotHandle, Letter[1], Length(Letter),

BytesWritten, nil);

// Сигнализируем об отправке данных через специальное событие

CommandEvent := OpenEvent(EVENT_MODIFY_STATE, False, EventName);

SetEvent(CommandEvent);

// Закрываем все дескрипторы

CloseHandle(CommandEvent);

CloseHandle(ClientMailslotHandle);

end;

 end

 else

 begin

// Создаем событие для сигнализирования о поступлении данных

CommandEvent := CreateEvent(nil, False, False, EventName);

// Выполняем обычный для VCL-приложений цикл

Application.Initialize;

Application.CreateForm(TDKSViewMainForm, DKSViewMainForm);

Application.Run;

// Закрываем все дескрипторы

CloseHandle(ServerMailslotHandle);

CloseHandle(CommandEvent);

 end;

end.

Теперь осталось "научить" первую копию приложения обнаруживать момент, когда в почтовом ящике оказываются сообщения, и забирать их оттуда. Было бы идеально, если при поступлении данных главная форма получала бы какое-то сообщение, но готового такого механизма, к сожалению, не существует. Из положения можно выйти, задействовав события.

Примечание

События — это объекты синхронизации, использующиеся в системе. Событие может быть взведено и сброшено. С помощью функции

WaitForSingleObject
можно перевести нить в состояние ожидания до тех пор. пока указанное событие не будет взведено. Подробное рассмотрение объектов синхронизации выходит за рамки нашей книги; они детально описаны, например, в [2].

В принципе, при использовании перекрытого ввода-вывода система может сама взводить указанное программой событие при получении данных почтовым ящиком, но перекрытый ввод-вывод имеет ограниченную поддержку в Windows 9х/МЕ и на почтовые ящики не распространяется. Чтобы приложение могло работать не только в Windows NT/2000/XP, мы не будем применять перекрытый ввод-вывод.

Поделиться:
Популярные книги

Корсар

Русич Антон
Вселенная EVE Online
Фантастика:
боевая фантастика
космическая фантастика
6.29
рейтинг книги
Корсар

Девяностые приближаются

Иванов Дмитрий
3. Девяностые
Фантастика:
попаданцы
альтернативная история
7.33
рейтинг книги
Девяностые приближаются

Жена фаворита королевы. Посмешище двора

Семина Дия
Фантастика:
фэнтези
5.00
рейтинг книги
Жена фаворита королевы. Посмешище двора

(не)Бальмануг. Дочь 2

Лашина Полина
8. Мир Десяти
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
(не)Бальмануг. Дочь 2

Буря империи

Сай Ярослав
6. Медорфенов
Фантастика:
аниме
фэнтези
фантастика: прочее
эпическая фантастика
5.00
рейтинг книги
Буря империи

Идеальный мир для Лекаря 13

Сапфир Олег
13. Лекарь
Фантастика:
фэнтези
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 13

Книга пятая: Древний

Злобин Михаил
5. О чем молчат могилы
Фантастика:
фэнтези
городское фэнтези
мистика
7.68
рейтинг книги
Книга пятая: Древний

Зеркало силы

Кас Маркус
3. Артефактор
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Зеркало силы

Имя нам Легион. Том 5

Дорничев Дмитрий
5. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 5

Аномальный наследник. Том 3

Тарс Элиан
2. Аномальный наследник
Фантастика:
фэнтези
7.74
рейтинг книги
Аномальный наследник. Том 3

Архил...? 4

Кожевников Павел
4. Архил...?
Фантастика:
фэнтези
попаданцы
альтернативная история
5.50
рейтинг книги
Архил...? 4

Хозяйка лавандовой долины

Скор Элен
2. Хозяйка своей судьбы
Любовные романы:
любовно-фантастические романы
6.25
рейтинг книги
Хозяйка лавандовой долины

Отмороженный 10.0

Гарцевич Евгений Александрович
10. Отмороженный
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Отмороженный 10.0

Ваше Сиятельство 2

Моури Эрли
2. Ваше Сиятельство
Фантастика:
фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Ваше Сиятельство 2