Последние записи
- TChromium (CEF3), сохранение изображений
- Как в Delphi XE обнулить таймер?
- Изменить цвет шрифта TextBox на форме
- Ресайз PNG без потери прозрачности
- Вывод на печать графического файла
- Взаимодействие через командную строку
- Перенести программу из Delphi в Lazarus
- Определить текущую ОС
- Автоматическая смена языка (раскладки клавиатуры)
- Сравнение языков на массивах. Часть 2
Интенсив по Python: Работа с API и фреймворками 24-26 ИЮНЯ 2022. Знаете Python, но хотите расширить свои навыки?
Slurm подготовили для вас особенный продукт! Оставить заявку по ссылке - https://slurm.club/3MeqNEk
Online-курс Java с оплатой после трудоустройства. Каждый выпускник получает предложение о работе
И зарплату на 30% выше ожидаемой, подробнее на сайте академии, ссылка - ttps://clck.ru/fCrQw
27th
Фев
Общение между запущенными копиями своих программ
Posted by Chas under Журнал, Статьи
Рассматривать задачу будем на конкретном примере некоего приложения. Опишем предметную область и постановку задачи: необходимо, чтобы наше приложение, зарегистрировав себя как протокол в системе Windows, при нажатии на ссылку вида testproject:\\xxxxx запустило наше приложение (если оно не запущено) и передало ему параметры ссылки. Если же приложение уже запущено, то необходимо запущенной копии приложения сообщить параметры ссылки.
Павел Добряков
by Квэнди http://kvendi.pp.ru
Что ж, задачу описали, приступим к реализации. Для примера я буду использовать BDS 2006. Создадим новый проект. Для начала нам необходимо зарегистрироваться в реестре, чтобы система воспринимала правильно наши ссылки, поэтому в uses главной формы дописываем модуль registry.
В событии Onactivate() главной формы пишем:
procedure Tfstart.FormActivate(Sender: TObject);
var reg: tregistry;
begin
reg:=tregistry.Create;
reg.RootKey:=HKEY_Classes_Root;
if not(reg.KeyExists(‘testproject’)) then begin
reg.OpenKey(‘testproject’,true);
reg.WriteString(”,’URL:testproject Protocol’);
reg.WriteString(‘URL Protocol’,”);
reg.OpenKey(‘DefaultIcon’,true);
reg.WriteString(”,application.ExeName);
reg.CloseKey;
reg.OpenKey(‘testproject\shell\open\command’,true);
reg.WriteString(”,application.ExeName+’ %1?);
reg.CloseKey;
end;
reg.Free;
end;
Соответственно мы имеем зарегистрированный в системе протокол под названием testproject. Проверить это можно достаточно простым способом: открываем любой браузер и в адресной строке набираем “testproject:\\eee”, после чего запустится ваша программа.
Теперь продолжим. Нам необходимо определять запущена-ли наша программа или нет. Для решения подобной задачи существует множество способов, но я предпочитаю способ с использованием мьютексов*. Не буду сейчас вдавать в подробности описания мьютексов и их использования. Итак, заходим в код нашего проекта и пишем там:
program testproject;
uses
Forms,windows,
Ustart in ‘Ustart.pas’ {fstart};
{$R *.res}
var HM: THandle;
function Check: boolean;
begin
HM := OpenMutex(MUTEX_ALL_ACCESS, false, ‘TestProjectMutex’);
Result := (HM <> 0);
if HM = 0 then HM := CreateMutex(nil, false, ‘TestProjectMutex’);
end;
begin
Application.Initialize;
Application.CreateForm(Tfstart, fstart);
Application.Run;
end.
В результате у нас есть функция, возвращающая true, если копия проекта запущена и false, если это первая копия. Далее нам необходимо понять запущено-ли приложение по ссылке или просто кто-то запустил наш exe-ник. Проверяется достаточно просто: при запуске по ссылке в наше приложение будет передан параметр командной строки, в котором будет сдержаться полностью строка ссылки, поэтому нам необходимо обработать только одно условие:
if (check)and(paramcount>0) then
begin
end;
Итак, что же мы будем делать, если такой процесс уже есть? Нам, соответственно, необходимо каким-то образом сообщить запущенному процессу те параметры, которые нам передали. Отсюда возникает вопрос: нам необходимо знать хэндл нашего уже запущенного приложения. Здесь все подвластно исключительно вашей фантазии, так как сделать это можно сколь угодно множеством способов. Я выберу далеко не лучший, но для примера: будем хранить хэндл в реестре. Для этого модифицируем Onactivate() нашей главной формы:
procedure Tfstart.FormActivate(Sender: TObject);
var reg:tregistry;
begin
reg:= tregistry.Create;
reg.RootKey:=HKEY_Classes_Root;
if not(reg.KeyExists(‘testproject’)) then begin
reg.OpenKey(‘testproject’,true);
reg.WriteString(”,’URL:testproject Protocol’);
reg.WriteString(‘URL Protocol’,”);
reg.OpenKey(‘DefaultIcon’,true);
reg.WriteString(”,application.ExeName);
reg.CloseKey;
reg.OpenKey(‘testproject\shell\open\command’,true);
reg.WriteString(”,application.ExeName+’ %1?);
reg.CloseKey;
end;
reg.RootKey:= HKEY_current_user;
reg.OpenKey(’software\testproject’,true);
reg.WriteInteger(‘handle’,fstart.Handle);
reg.CloseKey;
reg.Free;
end;
Далее добавим обработчик события CloseQuery() нашей формы:
procedure Tfstart.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
var reg: tregistry;
begin
reg:=tregistry.Create;
reg.RootKey:=HKEY_current_user;
reg.OpenKey(’software\testproject’, true);
reg.WriteInteger(‘handle’,0);
reg.CloseKey;
reg.Free;
end;
Таким образом, при закрытии программы мы будем обнулять наш хэндл. После чего, проверяем наличие копии уже запущенного приложения. Приведу сразу код:
program testproject;
uses
Forms,windows,registry,sysutils,messages,
Ustart in ‘Ustart.pas’ {fstart};
{$R *.res}
var HM,HForm: THandle;
reg: tregistry;
ParamCmd:TCopyDataStruct;
function Check: boolean;
begin
HM := OpenMutex(MUTEX_ALL_ACCESS, false, ‘TestProjectMutex’);
Result := (HM <> 0);
if HM = 0 then HM := CreateMutex(nil, false, ‘TestProjectMutex’);
end;
begin
if (check)and(paramcount>0) then begin
{Читаем handle запущенного приложения}
reg:= tregistry.Create;
reg.RootKey:=HKEY_current_user;
reg.OpenKey(’software\testproject’,true);
HForm:=reg.ReadInteger(‘handle’);
reg.CloseKey;
reg.Free;
{Составляем структуру данных ParamCmd}
with ParamCmd do begin
dwData := 0;
cbdata:=strlen(pchar(paramstr(1)))+1;
lpData:=pchar(paramstr(1));
end;
{Посылаем сообщение запущеной программе}
SendMessage(HForm, WM_COPYDATA,application.Handle,longint(@ParamCmd));
Exit;
end;
Application.Initialize;
Application.CreateForm(Tfstart, fstart);
Application.Run;
end.
Вот собственно и почти все. Сейчас наше приложение умеет уже обрабатывать полученные данные и отправлять их запущенной копии приложения. Но нам также необходимо, чтобы наша запущенная копия получила эти данные, поэтому дополним код модуля нашей основной формы:
unit Ustart;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,registry, StdCtrls;
type
Tfstart = class(TForm)
Label1: TLabel;
procedure FormActivate(Sender: TObject);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
protected
procedure Getmessage(var msg: TWMCopyData); message WM_COPYDATA;
private
{ Private declarations }
public
{ Public declarations }
end;
var
fstart: Tfstart;
implementation
{$R *.dfm}
procedure Tfstart.FormActivate(Sender: TObject);
var reg: tregistry;
begin
reg:= tregistry.Create;
reg.RootKey:=HKEY_Classes_Root;
if not(reg.KeyExists(‘testproject’)) then begin
reg.OpenKey(‘testproject’,true);
reg.WriteString(”,’URL:testproject Protocol’);
reg.WriteString(‘URL Protocol’,”);
reg.OpenKey(‘DefaultIcon’,true);
reg.WriteString(”,application.ExeName);
reg.CloseKey;
reg.OpenKey(‘testproject\shell\open\command’,true);
reg.WriteString(”,application.ExeName+’ %1?);
reg.CloseKey;
end;
reg.RootKey:=HKEY_current_user;
reg.OpenKey(’software\testproject’,true);
reg.WriteInteger(‘handle’,fstart.Handle);
reg.CloseKey;
reg.Free;
if paramcount>0 then // Если это первая копия программы,
label1.Caption:=paramstr(1); // то мы можем сразу смело обрабатывать наши параметры
end;
procedure Tfstart.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
var reg: tregistry;
begin
reg:= tregistry.Create;
reg.RootKey:=HKEY_current_user;
reg.OpenKey(’software\testproject’,true);
reg.WriteInteger(‘handle’,0);
reg.CloseKey;
reg.Free;
end;
procedure tfstart.Getmessage(var msg: TWMCopyData);
var sText: array[0..99] of Char;
begin
// Преобразуем полученные данные в строку
StrLCopy(sText, Msg.CopyDataStruct.lpData, Msg.CopyDataStruct.cbData);
label1.Caption:=stext;
end;
end.
Послесловие
Вот собственно и все. Достаточно просто проверить. Запустим первую копию нашего приложения, а затем в браузере наберем:
testproject:\\TEST
И увидим, как на нашей запущенной форме появится этот текст. Надеюсь, что эта информация пригодится вам.
Статья из десятого выпуска журнала «ПРОграммист».
Обсудить на форуме — Общение между запущенными копиями своих программ
Похожие статьи
Купить рекламу на сайте за 1000 руб
пишите сюда - alarforum@yandex.ru
Да и по любым другим вопросам пишите на почту
пеллетные котлы
Пеллетный котел Emtas
Наши форумы по программированию:
- Форум Web программирование (веб)
- Delphi форумы
- Форумы C (Си)
- Форум .NET Frameworks (точка нет фреймворки)
- Форум Java (джава)
- Форум низкоуровневое программирование
- Форум VBA (вба)
- Форум OpenGL
- Форум DirectX
- Форум CAD проектирование
- Форум по операционным системам
- Форум Software (Софт)
- Форум Hardware (Компьютерное железо)