2015-02-12 3 views
1

У меня проблема с сервисом, который я закодировал в Delphi. Это не начинается, и я не могу найти проблемы с этим. Он работал хорошо 2 недели назад и без каких-либо изменений в сервисе, он внезапно прекратил работать. Служба отвечает за обновление огромной системы, но она не зависит от if. Моя служба получает URL-адрес исправления, загружает его и выполняет его. Ни больше ни меньше. Система, которую предполагается обновить, имеет некоторые другие сервисы и прочее, работающие в фоновом режиме, поэтому у нее есть небольшой инструмент для перезапуска всех фоновых файлов сразу (включая мой сервис). В моем офисе у нас есть около 70 компьютеров, каждый день работающие с системой дыр с моим сервисом, и он работает нормально. У нас почти все версии окон (XP, Windows 7, Windows 8, Windows Server 2003 и даже Windows 10). Однажды внезапно, он прекратил перезапуск с помощью этого маленького инструмента, о котором я вам рассказывал. Первое, что мне пришло в голову, - попытаться запустить его вручную, но и не повезло. Моя самая большая проблема, я не знаю, что может произойти. Единственное место, где я могу видеть какой-то журнал, - это диспетчер событий Windows, и это совсем не полезно. Ошибка говорит:Служба Delphi не запустится

The XXX service failed to start due to the following error: The service did not respond to the start or control request in a timely fashion.

Я искал в Интернете и не мог найти что-нибудь полезное. Все страницы, связанные с этой ошибкой, говорят о том, что эта ошибка имеет какое-то отношение к тайм-ауту служб Windows или что она имеет какое-то отношение к NetFramework 1.1 и серверу Windows 2003. Это не тот случай, мы установили NetFramework 4 с последним обновлением на некоторых компьютерах, где он сбой, и, как я уже сказал, это может привести к разным версиям окон. О тайм-ауте ошибка отображается сразу после того, как я нажимаю start в диспетчере сервисов, она не будет ждать 30-секундного таймаута.

У меня в машине есть журнал, но это бесполезно, ошибка происходит где-то до метода «ServiceStart». У меня есть этот код:

procedure TMyService.ServiceStart(Sender: TService; var Started: Boolean); 
begin 
    try 
    LogFile.Write('TTMyService.ServiceStart'); //This is my logging machine 
    Started := True; 
    InitializeService; //Sets some variables 
    InitializeTimer; //Start a timer where all the magic happens 
    except 
    on e:Exception Do 
     LogFile.Write('TTMyService.ServiceStart - ' + e.Message); 
    end; 
end; 

Это ничего не каротаж, даже не «TMyService.ServiceStart». Одна идея, которую я имел, но она не работает, заключается в замене класса TApplication VCL. Я скопировал все содержимое файла «Vcl.SvcMgr» на новый, изменив его, как это (я только добавил LogFile.Write Материал):

procedure TServiceApplication.Run; 
var 
    ServiceStartTable: TServiceTableEntryArray; 
    ServiceCount, i, J: Integer; 
    StartThread: TServiceStartThread; 
begin 
{$IF NOT DEFINED(CLR)} 
    AddExitProc(DoneServiceApplication); 
{$ENDIF} 
    if FindSwitch('INSTALL') then 
    RegisterServices(True, FindSwitch('SILENT')) 
    else if FindSwitch('UNINSTALL') then 
    RegisterServices(False, FindSwitch('SILENT')) 
    else 
    begin 
    Vcl.Forms.Application.OnException := OnExceptionHandler; 
    ServiceCount := 0; 
    for i := 0 to ComponentCount - 1 do 
     if Components[i] is TService then Inc(ServiceCount); 
    SetLength(ServiceStartTable, ServiceCount + 1); 
{$IF NOT DEFINED(CLR)} 
    FillChar(ServiceStartTable[0], SizeOf(TServiceTableEntry) * (ServiceCount + 1), 0); 
{$ENDIF} 
    J := 0; 
    for i := 0 to ComponentCount - 1 do 
     if Components[i] is TService then 
     begin 
{$IF DEFINED(CLR)} 
     ServiceStartTable[J].lpServiceName := Components[i].Name; 
     ServiceStartTable[J].lpServiceProc := ServiceMainDelegate; 
{$ELSE} 
     ServiceStartTable[J].lpServiceName := PChar(Components[i].Name); 
     ServiceStartTable[J].lpServiceProc := @ServiceMain; 
{$ENDIF} 
     Inc(J); 
     end; 
    StartThread := TServiceStartThread.Create(ServiceStartTable); 
    try 
     while not Vcl.Forms.Application.Terminated do 
     try 
     Vcl.Forms.Application.HandleMessage; 
     except 
     on E: Exception do 
     begin 
      LogFile.Write('TServiceApplication.Run - ' + e.Message); 
      DoHandleException(E); 
     end; 
     end; 
     Vcl.Forms.Application.Terminate; 
{$IF DEFINED(CLR)} 
     DoneServiceApplication; 
{$ENDIF} 
     if StartThread.ReturnValue <> 0 then 
     begin 
     LogFile.Write('TServiceApplication.Run - ' + SysErrorMessage(StartThread.ReturnValue)); 
     FEventLogger.LogMessage(SysErrorMessage(StartThread.ReturnValue)); 
     end; 
    finally 
     StartThread.Free; 
    end; 
    end; 
end; 

Sorry, I don't know how to mark my changes in bold or in red to make it easier for you to see them

Это работает, теперь Я могу получить «полезный» журнал, но он тоже не помогает. Я получаю:

TServiceApplication.Run - The parameter is incorrect

И служба не будет больше в моей машине (где он все еще работает). До сих пор я точно знаю 15 машин, где он не работает, и у меня нет доступа к попыткам в другом 65. Как-то на моей машине, где я разрабатываю службу, она все еще работает, если я прокомментирую «Tapplication "изменения.

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

Прежде чем я забуду, не знаю, действительно ли это актуально, но чтобы получить URL-адрес исправления, служба подключается (на моей машине) к локальной веб-службе, размещенной в IIS.

Любые идеи? Это достаточно ясно? У вас есть сомнения, пожалуйста, спросите их!: D Я действительно потерял, и это имеет первостепенное значение: '(

Спасибо заранее Николаса Лопеса

Новые данные 1:

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

ответ

1

Ваше сообщение журнала TServiceApplication.Run - The parameter is incorrect означает, что StartThread.ReturnValue 87 (ERROR_INVALID_PARAMETER). единственный способ, который может произойти, если StartServiceCtrlDispatcher() не удалось при вызове TServiceStartThread.Execute(). StartServiceCtrlDispatcher() принимает только 1 параметр - массив ServiceStartTable, который устанавливает TServiceApplication.Run(). Этот массив содержит имена служб и Main() обратные вызовы для приема сообщений SCM. Так что что-то не так с этим массивом, и вам нужно выяснить, что это такое. Вероятно, он неправильно заполнен или поврежден до того, как вызывается StartServiceCtrlDispatcher().

Чтобы диагностировать возникшую проблему, вам необходимо будет использовать отладчик IDE для входа в стартовый код TService. Это означает использование функции отладки Attach to Process, так как IDE не может автоматически запустить службу для отладки. Сначала необходимо сначала запустить SCM, а затем приложить отладчик к результирующему процессу (установите флажок «Показывать системные процессы» в диалоговом окне присоединения). Это также означает настройку кода проекта, чтобы сделать задержку запуска до тех пор, пока не будет подключен отладчик. Обычно я обрабатываю это в событии OnStart, вызывая IsDebuggerPresent() в цикле, но поскольку ваш OnStart не запускается, вам придется выполнять задержку раньше в логике запуска, например, в главном DPR до того, как TApplication начинает инициализацию объекта TService ,

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

+0

Remy, Спасибо за ответ, но я не думаю, что это проблема моего обслуживания. Единственный способ получить эту ошибку - после того, как я изменил ее, чтобы использовать мою собственную версию 'Vcl.SvcMgr', иначе она будет работать нормально на моей машине. Я прокомментировал это, потому что думал, что кому-то может быть полезно знать это. Я думаю, что реальная проблема службы в другом месте. Вероятно, проблема с массивом заключается в том, что в какой-то единице используется исходный 'Vcl.SvcMgr'. Я знаю свою попытку исправить ее, изменив ее, это не самый здоровый, но мне все равно пришлось попробовать это;) Я немного потерялся здесь ... – NicolasLopezG

+0

Давайте работать в обратном направлении. Единственный способ, с помощью которого 'OnStart' не запускался (при условии, что он назначен), - это если объект службы TServiceThread не создается вообще или завершается до вызова метода' Execute() '(' TThread' проверяет его свойство «Terminated» перед вызовом 'Execute()'). 'TServiceThread' не создается, если' TService.Main() 'не вызывается, или если' RegisterServiceCtrlHandler() 'терпит неудачу при вызове' TService.Main() '... –

+0

...' Main() 'is not если 'TServiceApplication.DispatchServiceMain()' вообще не вызывается или не находит объект 'TService', чье' Name' соответствует имени, переданному как параметр 'Main()'. 'DispatchServiceMain()' не вызывается, если 'ServiceMain()' не вызывается. И 'ServiceMain()' не вызывается, если 'StartServiceCtrlDispatcher()' терпит неудачу. –

1

Я столкнулся с аналогичной проблемой:

  • The XXX service failed to start due to the following error: The service did not respond to the start or control request in a timely fashion.

  • в TService.OnStart или TService.OnExecute события, где никогда не стреляли. Путь
  • Услуг, чтобы исполняемые файлы (services.msc -> правой кнопкой мыши на службе -> свойства) был установлен следующим образом: C:\test\TrucServer.exe /startedbyscm:A357F915-40E33CD5-trucServer

=> Решение было переустановить службу (деинсталляция sc.exe delete "Truc Server", то установите C:\test\TrucServer.exe -install). Теперь путь к исполняемым файлам сервисов задан следующим образом: C:\test\TrucServer.exe и служба запускается нормально.

Я не пытался вставить журналы в классе TServiceApplication, но ваше сообщение об ошибке: TServiceApplication.Run - The parameter is incorrect, кажется, подтверждает мое решение может соответствовать вашей проблеме, как в моем случае параметр /startedbyscm:A357F915-40E33CD5-trucServer, кажется, виновник.

Я не пытался отслеживать сообщение об ошибке в Vcl.SvcMgr.

+0

Спасибо @Souch – NicolasLopezG

+0

Я точно не помню, но я исправил это давным-давно. Если я правильно помню, это была проблема с компонентом, у которого неправильный параметр, заданный при проектировании. Моя служба подключается к серверу, чтобы сделать это. Я думаю, что это был URL-адрес или порт, или что-то в этом роде было не так, поскольку оно было исправлено в компоненте при разработке, сервис даже не запустится. Есть ли способ закрыть этот вопрос? – NicolasLopezG

0

В моем случае проблема была TServiceDesc.displayName. Я попытался установить /install и /uninstall, а при удалении имя не удалось найти. Поскольку он не найден на /uninstall, диспетчер сервера не мог обнаружить, что он запустился.Таким образом, статус в «Сервисах» всегда был «Starting». Почему некоторые имена в порядке, а другие - я не могу сказать. В этом нет ничего особенного.

DisplayName := "Name DB Service"; 

Это не сработало. Поэтому я сделал exe и displayName точно так же. Непонятно, как это происходит, но причиной ошибки является имя формы службы, имя исполняемого файла и DisplayName. Все эти три вместе как-то перепутались.