Можно ли установить несколько экземпляров одного и того же приложения-службы delphi?

У меня есть приложение-служба, построенное в Delphi, которое отлично работает. Он делает именно то, что я хочу, и все счастливы. Все в порядке, пока я не захочу запустить два (или более) экземпляра этой службы на одной машине. Поскольку имя службы жестко закодировано в программе (через свойство Name службы), я могу установить службу только один раз на любом компьютере. Если я попытаюсь изменить свойство Name во время выполнения, служба не ответит, если свойство Name не установлено в значение то же самое, что было установлено во время проектирования.

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

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

есть ли способ изменить свой код, чтобы у меня был только один проект Delphi, который может устанавливать и запускать себя как несколько экземпляров службы с некоторым простым входом во время выполнения (например, флаг командной строки)?

или, возможно, более широкий вопрос: есть ли "правильный путь", чтобы достичь цели?

5 ответов


вы не дали понять, что вы пытались изменить в подклассе TService.

вы добавили обработчик" BeforeInstall"?

что-то типа:

procedure TServiceMain.ServiceLoadInfo(Sender : TObject);// new method, not an override
begin
  Name := ParamStr(2);
  DisplayName := ParamStr(3);
end;

procedure TServiceMain.ServiceBeforeInstall(Sender: TService);
begin
  ServiceLoadInfo(Self);
end;
procedure TServiceMain.ServiceCreate(Sender: TObject);
begin
  ServiceLoadInfo(Self);
end;

Если вы делаете это регулярно, подкласс TService для выполнения thie в конструкторе.

вы также должны сделать то же самое в BeforeUninstall - указать оба события одним и тем же методом.

C:\>servicename /install MyService "My Service Description"

вы можете создать свой сервис с несколькими потоками внутри, каждый из которых действует как собственная версия / копия сервиса. Вы управляете им с помощью API контроллера службы, IIRC.


Ну да, можно установить несколько экземпляров одной и той же службы, вам просто нужно динамически изменять имя во время установки (не во время выполнения), однако это не делает его желательным. (есть некоторый пример кода в проекте кодаhttp://www.codeproject.com/KB/dotnet/MultipleInstNetWinService.aspx)

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


обернуть весь код в класс, который наследуется от TThread.

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

каждый экземпляр работает независимо.

изменить количество экземпляров можно отключить услугу, изменить настройки (в файле или реестре) и перезапустить службу.


принятый ответ выше был ужасно полезным.

код, который я использовал:

procedure TService1.ServiceAfterInstall(Sender: TService);
begin
//http://stackoverflow.com/questions/612587/is-it-possible-to-install-multiple-instances-of-the-same-delphi-service-applicati
//http://www.c-sharpcorner.com/UploadFile/timosten/DynamicServiceInCSharp11262005062503AM/DynamicServiceInCSharp.aspx?ArticleID=4d5020e4-7317-425c-ab29-5bf37a1db421
//http://support.microsoft.com/kb/137890
  SaveRegSetting('\SYSTEM\CurrentControlSet\Services\' + Name, 'ImagePath', ParamStr(0) + ' --name=' + Name, HKEY_LOCAL_MACHINE)
end;

procedure TService1.ServiceCreate(Sender: TObject);
begin
  Name := Trim(FCommandLineOptions.Values['name']);
  DisplayName := Name;
end;

SaveRegSetting-это моя собственная процедура, а FCommandLineOptions-объект, который обозначает параметры командной строки.