Автономное приложение Delphi, которое может также быть установлено как сервис окон

В Delphi можно создать автономное приложение Windows VCL Forms. Можно также создать приложение службы Windows.

Действительно ли возможно объединить два в отдельном приложении, которое может работать как автономное приложение и может также быть установлено как служба Windows?

32
задан ThinkingStiff 10 March 2013 в 01:49
поделиться

3 ответа

Абсолютно возможно. Фокус в том, чтобы отредактировать .dpr для создания главной формы, когда вы хотите запустить ее как приложение, и служебной формы, когда вы хотите запустить ее как службу. Например, так:

if SvComFindCommand('config') then begin
  //When run with the /config switch, display the configuration dialog.
  Forms.Application.Initialize;
  Forms.Application.CreateForm(TfrmConfig, frmConfig);
  Forms.Application.Run;
end
else begin
  SvCom_NTService.Application.Initialize;
  SvCom_NTService.Application.CreateForm(TscmServiceSvc, scmServiceSvc);
  SvCom_NTService.Application.Run;
end;

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

Я написал статью об этом для журнала The Delphi Magazine много лет назад. Вы можете прочитать ее здесь: Many Faces Of An Application.

49
ответ дан 27 November 2019 в 20:30
поделиться

Это возможно, но в этом случае вы не сможете использовать обычные TServiceApplication и TService. Вы должны реализовать весь код, специфичный для сервиса, самостоятельно.

У нас была похожая проблема, и мы сделали два каркасных приложения: одно для отдельного exe для песка и одно для сервиса. Теперь мы можем создать один BPL/DLL, который будет встроен в оба контейнера.

Если вы хотите потратить немного денег: вам стоит посмотреть на SvCOM, я думаю, у них есть решение проблемы.

1
ответ дан 27 November 2019 в 20:30
поделиться

Это будет сложно объяснить, но я попробую :)

Я сделал это в своем проекте вот так (Delphi 5):

program TestSvc;
uses SvcMgr, 
     SvcMain, //the unit for TTestService inherited from TService
     ...
     ;

var
  IsDesktopMode : Boolean;

function IsServiceRunning : Boolean;
var
  Svc: Integer;
  SvcMgr: Integer;
  ServSt : TServiceStatus;
begin
  Result := False;
  SvcMgr := OpenSCManager(nil, nil, SC_MANAGER_CONNECT);
  if SvcMgr = 0 then Exit;
  try
    Svc := OpenService(SvcMgr, 'TestService', SERVICE_QUERY_STATUS);
    if Svc = 0 then Exit;
    try
      if not QueryServiceStatus(Svc, ServSt) then Exit;
      Result := (ServSt.dwCurrentState = SERVICE_RUNNING) or (ServSt.dwCurrentState = SERVICE_START_PENDING);
    finally
      CloseServiceHandle(Svc);
    end;
  finally
    CloseServiceHandle(SvcMgr);
  end;
end;


begin
  if (Win32Platform <> VER_PLATFORM_WIN32_NT) or FindCmdLineSwitch('S', ['-', '/'], True)  then
    IsDesktopMode := True
  else begin
    IsDesktopMode := not FindCmdLineSwitch('INSTALL', ['-', '/'], True) and
      not FindCmdLineSwitch('UNINSTALL', ['-', '/'], True) and
      not IsServiceRunning;
  end;

  if IsDesktopMode then begin //desktop mode
    Forms.Application.Initialize;
    Forms.Application.Title := 'App. Title';
    ShowTrayIcon(Forms.Application.Icon.Handle, NIM_ADD); // This function for create an icon to tray. You can create a popupmenu for the Icon.

    while GetMessage(Msg, 0, 0, 0) do begin
      TranslateMessage(Msg);
      DispatchMessage(Msg);
    end;

    ShowTrayIcon(Forms.Application.Icon.Handle, NIM_DELETE); // for delete the tray Icon
  end else begin // Service mode
    SvcMgr.Application.Initialize;
    SvcMgr.Application.CreateForm(TTestService, TestService);
    SvcMgr.Application.Run;
  end;
end.
9
ответ дан 27 November 2019 в 20:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: