#windows #delphi #service
Вопрос:
Я пишу базовую службу Delphi MS-Windows. Я устанавливаю его с помощью /install directove. Это работает. В списке служб Windows он существует. Я начинаю с этого. Windows говорит, что все началось успешно. Он отображается как запущенный. Но ничего не выполняется, кроме onCreate и onDestroy.
Он на самом деле НЕ работает, в то время как Windows утверждает, что он работает.
Я попробовал Delpi 10.2 и последнюю версию 10.4.
Что здесь происходит не так? Это самая простая из возможных Услуг.
Вывод журнала выглядит следующим образом:
Create
AfterInstall
Destroy
Create
Destroy
Create
Destroy
program BartServiceTwo;
uses
Vcl.SvcMgr,
Unit1 in 'Unit1.pas' {BartService: TService};
{$R *.RES}
begin
// Windows 2003 Server requires StartServiceCtrlDispatcher to be
// called before CoRegisterClassObject, which can be called indirectly
// by Application.Initialize. TServiceApplication.DelayInitialize allows
// Application.Initialize to be called from TService.Main (after
// StartServiceCtrlDispatcher has been called).
//
// Delayed initialization of the Application object may affect
// events which then occur prior to initialization, such as
// TService.OnCreate. It is only recommended if the ServiceApplication
// registers a class object with OLE and is intended for use with
// Windows 2003 Server.
//
// Application.DelayInitialize := True;
//
if not Application.DelayInitialize or Application.Installing then
Application.Initialize;
Application.CreateForm(TBartService, BartService);
Application.Run;
end.
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes, Vcl.SvcMgr;
type
TBartService = class(TService)
procedure ServiceExecute(Sender: TService);
procedure ServiceCreate(Sender: TObject);
procedure ServiceDestroy(Sender: TObject);
procedure ServiceStart(Sender: TService; var Started: Boolean);
procedure ServiceStop(Sender: TService; var Stopped: Boolean);
procedure ServiceAfterInstall(Sender: TService);
private
{ Private declarations }
public
function GetServiceController: TServiceController; override;
procedure Log(Line:string);
{ Public declarations }
end;
var
BartService: TBartService;
LogFile: text;
Logfilename: string;
implementation
{$R *.dfm}
procedure TBartService.Log(Line:string);
begin
if Logfilename = '' then
begin
Logfilename := 'Log.txt';
Assignfile(LogFile,Logfilename);
end;
try
if FileExists(Logfilename)
then append(LogFile)
else rewrite(LogFile);
writeln(LogFile,line);
Closefile(LogFile);
except
on E:Exception do;
end;
end;
procedure ServiceController(CtrlCode: DWord); stdcall;
begin
BartService.Controller(CtrlCode);
end;
function TBartService.GetServiceController: TServiceController;
begin
Result := ServiceController;
end;
procedure TBartService.ServiceAfterInstall(Sender: TService);
begin
Log('AfterInstall');
end;
procedure TBartService.ServiceCreate(Sender: TObject);
begin
Log('Create');
messagebeep(0);
end;
procedure TBartService.ServiceDestroy(Sender: TObject);
begin
Log('Destroy');
end;
procedure TBartService.ServiceExecute(Sender: TService);
begin
Log('ServiceExecute Start. Terminated=' Terminated.ToString(true));
while not Terminated do
begin
try
ServiceThread.ProcessRequests(false);
Log('ServiceExecute');
// messagebeep(0);
sleep(1000);
except
on E:Exception do
begin
Log('ERROR: ServiceExecute: Final: ' E.Message);
end;
end;
end;
Log('ServiceExecute Out of loop.');
end;
procedure TBartService.ServiceStart(Sender: TService; var Started: Boolean);
begin
Log('ServiceStart');
end;
procedure TBartService.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
Log('ServiceStop');
end;
end.
Комментарии:
1. » Windows утверждает, что она запущена » — просто обновите список служб (F5) или снова откройте окно сведений, оба не обновляются. Говорят ли что — нибудь журналы событий ?
2. Есть ли причина, по которой вы регистрируетесь в файле (и почему вы закрываете и снова открываете его при каждом сообщении), а не регистрируетесь в журнале системных событий ?
TService
естьLogMessage()
метод для этой цели. В любом случае, можете ли вы показать своиDFM
? Вы УВЕРЕНЫ, что ваши обработчики событий на самом деле подключены правильно? Можете ли вы проверить это во время выполнения? Мне действительно кажется любопытным, что вы не получаетеOnStart
иOnExecute
события уволены. Я используюTService
его уже много лет (хотя и в более старых версиях), и он отлично работает для меня. Я не могу представить, чтобы Embarcadero нарушил его в современных версиях…3. … Вы пробовали включить отладочные контроллеры постоянного тока, а затем войти в
TService
исходный код во время выполнения, чтобы увидеть, что происходит на самом деле? Чтобы убедитьсяServiceThread
, что он действительно запущен? В вашем журнале показано 2 набора Create Destroy, после установки службы, были ли это 2 отдельные попытки запустить службу?4. @RemyLebeau; Я
TService
ежедневно использую Delphi 10.4. Это работает просто отлично.5. @AndreasRejbrand Я уверен, что это действительно работает.
TService
на самом деле он не изменился за последние годы. Это меня не удивляет. Что меня действительно удивляет, так это то, что описал ОП. Таким образом, здесь должен быть какой-то другой фактор, который еще не был описан/замечен.
Ответ №1:
Я предполагаю, что во время отладки вы скопировали и вставили код в устройство из другого проекта, но вы не «подключили» события должным образом. Откройте проект на Delphi и откройте сервисный модуль. Нажмите на вкладку События в Инспекторе объектов, и я предполагаю, что все они пусты. (Просмотрите источник файла .dfm, и, скорее всего, не будут определены события OnExecute, onStop, onStop и т. Д.)
Например, дважды щелкните событие OnExecute, и я предполагаю, что среда IDE автоматически создаст новое событие OnExecute, а не перейдет к вашему событию OnExecute в блоке.
Просто повторно подключите свои мероприятия, и, скорее всего, все будет работать так, как ожидалось.
Ответ №2:
Решенный. После использования системы ‘LogMessage() я обнаружил, что служба фактически запущена. Но случилось то, что папка назначения моего простого файла журнала была перенесена из локального исполняемого каталога в C:WindowsSystem32 и там были все остальные данные журнала… Я никогда не ожидал, что 🙁
Спасибо за всю помощь, Барт
Комментарии:
1. Подумайте о добавлении отметок времени в каждую строку вашего журнала, так как это делает такие ошибки более очевидными.