Entwickler-Ecke
Windows API - Windows Dienst kriegt nicht alle OnXXXX
HelgeLange - Mi 07.12.11 17:36
Titel: Windows Dienst kriegt nicht alle OnXXXX
Hallo,
ich habe mal wieder ein Problem :(
Ich habe mit DelphiXE einen Windows-Dienst geschrieben (nachdem ich es mit Delphi 2007 ohne Erfolg versucht habe, da ging garkein Event).
Mein Rechner ist ein Win7 64 bit und der Dienst läuft einwandfrei. Auch auf dem Firmenserver mit Windows Server 2008 32bit geht alles klasse.
Jetzt wollten wir den Dienst probeweise auf anderen Konfigurationen installieren (namentlich WinXP 32 und Vista 32) und sie starten nicht. Ich habe mir eine Anwendung geschrieben, die alle wichtigen Funktionen des Dienstes emuliert, die geht ohne Probleme.
Habe dann einige LogMessages eingebaut und er kommt zwar in ServiceCreate (ohne Fehler und führt alles aus), aber nie in ServiceStart (erste Linie ist ein Log-Eintrag, der erscheint aber nie). Aber wie gesagt, auf meinem Rechner und dem Server läuft es
Hier der Code des Services :
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114:
| unit svcMain;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs, ExtCtrls, uMAF_ManagerLoader, uMAF_Core, uMAF_HookClient, uMAF_Globals, uPTI_LogFile;
type TSIERP_WXService = class(TService) IdleTimer: TTimer; ML: TmafManagerLoader; HC: TmafHookClient; procedure ServiceStart(Sender: TService; var Started: Boolean); procedure ServiceStop(Sender: TService; var Stopped: Boolean); procedure MLDataLoad(Sender: TObject; Manager: string; var ManagerFileName: string); procedure IdleTimerTimer(Sender: TObject); procedure ServiceExecute(Sender: TService); procedure ServiceCreate(Sender: TObject); procedure ServiceDestroy(Sender: TObject); private public function GetServiceController: TServiceController; override; end;
var SIERP_WXService: TSIERP_WXService;
implementation
{$R *.DFM}
procedure ServiceController(CtrlCode: DWord); stdcall; begin SIERP_WXService.Controller(CtrlCode); end;
function TSIERP_WXService.GetServiceController: TServiceController; begin Result := ServiceController; end;
procedure TSIERP_WXService.MLDataLoad(Sender: TObject; Manager: string; var ManagerFileName: string); begin LogToFile('Requested Manager: ' + Manager); ManagerFileName := 'svcRouter_UniDAC.dll'; end;
procedure TSIERP_WXService.ServiceCreate(Sender: TObject); begin bRunMode := True; LogToFile('TSIERP_WXService.ServiceCreate'); LogToFile('ML.ConnectManager start'); ML.ConnectManager; LogToFile('ML.ConnectManager done'); end;
procedure TSIERP_WXService.ServiceDestroy(Sender: TObject); begin LogToFile('TSIERP_WXService.ServiceDestroy'); end;
procedure TSIERP_WXService.ServiceExecute(Sender: TService); begin While Not Terminated Do ServiceThread.ProcessRequests(True); end;
procedure TSIERP_WXService.ServiceStart(Sender: TService; var Started: Boolean); begin LogToFile('TSIERP_WXService.ServiceStart begin');
try bDebug := True; LogToFile('HC.SetGlobalBoolean start'); HC.SetGlobalBoolean('Debug', True, [vfSave], lsINIFile); LogToFile('HC.SetGlobalBoolean done');
LogToFile('HC.ExecuteHook(HK_INIT_SERVICE) start'); HC.ExecuteHook(10000); LogToFile('HC.ExecuteHook(HK_INIT_SERVICE) end'); IdleTimer.Enabled := True; Started := True; except on E: Exception do begin LogToFile('Exception: ' + E.Message); Started := False; end; end; LogToFile('TSIERP_WXService.ServiceStart end'); end;
procedure TSIERP_WXService.ServiceStop(Sender: TService; var Stopped: Boolean); begin IdleTimer.Enabled := False; HC.ExecuteHook(10001); ML.DisconnectManager; Stopped := True; end;
procedure TSIERP_WXService.IdleTimerTimer(Sender: TObject); begin IdleTimer.Enabled := False; Try ML.ProcessApplication_OnIdle; except on E: Exception do LogMessage(E.Message); End; IdleTimer.Enabled := True; end; |
und das Logfile von meinem Rechner (wo der Service geht) :
Zitat: |
10:26 a.m. - Requested Manager: HookManager
10:26 a.m. - Requested Manager: LinkManager
10:26 a.m. - Requested Manager: GlobalVars
10:26 a.m. - TSIERP_WXService.ServiceCreate
10:26 a.m. - ML.ConnectManager start
10:26 a.m. - ModulePath = C:\Program Files (x86)\WXServer\Modules\
10:26 a.m. - Database = C:\WXDatos\WXServiceDB.fdb
10:26 a.m. - DB connected
10:26 a.m. - HookManager connected
10:26 a.m. - hooks loaded=4
10:26 a.m. - modules loaded=4
10:26 a.m. - ML.ConnectManager done
10:26 a.m. - TSIERP_WXService.ServiceStart begin
10:26 a.m. - HC.SetGlobalBoolean start
10:26 a.m. - HC.SetGlobalBoolean done
10:26 a.m. - HC.ExecuteHook(HK_INIT_SERVICE) start
10:26 a.m. - WXServer.Listen
10:26 a.m. - Enter __InitModule
10:26 a.m. - Leave __InitModule
10:26 a.m. - HC.ExecuteHook(HK_INIT_SERVICE) end
10:26 a.m. - TSIERP_WXService.ServiceStart end
|
und das Logfile von einem der Rechner, wo es nicht geht :
Zitat: |
7:45 PM - Requested Manager: HookManager
7:45 PM - Requested Manager: LinkManager
7:45 PM - Requested Manager: GlobalVars
7:45 PM - TSIERP_WXService.ServiceCreate
7:45 PM - ML.ConnectManager start
7:45 PM - ModulePath = C:\Program Files\WXServer\Modules\
7:45 PM - Database = C:\WXDatos\WXServiceDB.fdb
7:45 PM - DB connected
7:45 PM - HookManager connected
7:45 PM - hooks loaded=4
7:45 PM - modules loaded=4
7:45 PM - ML.ConnectManager done |
Hat jemand schonmal so ein Problem gehabt und eine Idee, was das sein könnte ?
Danke schonmal
jaenicke - Mi 07.12.11 18:04
Wenn du das im lokalen Netzwerk reproduzieren kannst, wäre es wohl am einfachsten einfach mal den Remotedebugger zu bemühen. ;-)
HelgeLange - Mi 07.12.11 18:15
Ich reproduziere das in 2 VMs hier im eigenen Rechner. Debugging habe ich auch schonmal dran gedacht, nur bietet mir Delphi beim Attach Process den Process nicht an, hehe
Habs auch mit Sleep probiert, dem ganzen etwas Zeit zu geben, dammit man sich verbinden kann etc.
Ich habe auch mal den ganzen Code jetzt von ServiceStart in ServiceCreate bewegt (ausser dem Starten der des Timers und dem Setzen der Variable Started). Er führt alles ohne Probleme aus, keine Exception, kommt aber trotzdem nie dazu, ServiceStart auszuführen.
Remote-Debugging habe ich noch nie probiert :(
Mal im Netz nachschaun, wie das genau geht und was ich auf der VM installieren muss.
HelgeLange - Mi 07.12.11 19:17
Ich vermute fast, dass es eine fehlende DLL oder so ist, ich habe gerade den Service auf dem Rechner meiner Frau installiert, die hat auch ein Win7 64bit, aber frisch installiert vor 2 Wochen. Da ist weder Delphi noch sonstirgendwas drauf. Und der Service hängt dort auch.
Gibt es eine Möglichkeit zu sehen, was der alles so lädt ?
Boldar - Mi 07.12.11 19:22
ProcMon von Sysinternals.
HelgeLange - Mi 07.12.11 20:01
Ok, man sieht, was für DLLs geladen werden. Auch das Eventlog hat viele Informationen, aber nix, was hilft. Sieht alles ok und dann hört es abrupt auf mit Thread_exits :(
jaenicke - Mi 07.12.11 20:24
Starte Delphi bzw. den Remotedebugger mit Adminrechten, dann kannst du auch einen Dienst debuggen.
Ich vermute bei dir reicht vielleicht auch schon OnException einer TApplicationEvents Komponente auf deinem Servicemodul. Falls da eine auftritt, solltest du die in das Systemlog schreiben.
Mehr ggf. zu Hause, am Handy kann ich grad nicht so gut schauen...
HelgeLange - Mi 07.12.11 20:53
jaenicke hat folgendes geschrieben : |
Starte Delphi bzw. den Remotedebugger mit Adminrechten, dann kannst du auch einen Dienst debuggen.
Ich vermute bei dir reicht vielleicht auch schon OnException einer TApplicationEvents Komponente auf deinem Servicemodul. Falls da eine auftritt, solltest du die in das Systemlog schreiben.
Mehr ggf. zu Hause, am Handy kann ich grad nicht so gut schauen... |
Ich habe eine TApplicationEvents Komponente mal mit in den Service eingebaut und schreibe eine logmessage in mein logfile im Event OnException. Leider nichts. Er führt ServiceCreate aus (und loggt das) und dann ist stille. Das Schreiben des Logs ist auch das letzte in ServiceCreate, danach kommt nur noch das "end;" der Procedure :(
Selbst wenn das mit den Adminrechten geht, was soll ich denn da debuggen, wenn er erst garnicht in das event kommt.
Wundere mich eh, warum ich soviele Probleme habe, einen service zu schreiben. In Delphi 2007 hab ich es garnicht hinbekommen, nichtmal der leere automatisch von Delphi erstellte Service ging da :(
Habt Ihr die gleichen Probleme oder geht immer alles auf Anhieb ?
jaenicke - Mi 07.12.11 21:56
HelgeLange hat folgendes geschrieben : |
Selbst wenn das mit den Adminrechten geht, was soll ich denn da debuggen, wenn er erst garnicht in das event kommt. |
Vorher eine Endlosschleife, die du im Debugger mit dem Setzen einer Variable beenden kannst, Haltepunkt gesetzt und los gehts. ;-)
HelgeLange hat folgendes geschrieben : |
Habt Ihr die gleichen Probleme oder geht immer alles auf Anhieb ? |
Mit Delphi hatte ich da noch keinerlei Probleme. Wenn da etwas schief geht, ist wohl eher mit dem System was nicht in Ordnung. :gruebel:
Mit Lazarus hatte ich Probleme, aber abgesehen von den für Lazarus vollkommen normalen Problemen beim Arbeiten damit allgemein lief der Dienst dann nach einem Hinweis auf den Bugtracker, in dem ein seit einem Jahr vorhandener, aber nicht releaster Bugfix stand.
HelgeLange - Mi 07.12.11 22:47
Naja, debuggen auf meinem Arbeitsrechner geht jetzt, Delphi als Admin ausführen und schon zeigt er den Service an.
kleiner Tipp wegen der Variable, es geht auch IsDebuggerPresent als Bedingung für ein Repeat-Until.
Jetzt installiere ich mal alles auf der VM und teste dort.
jaenicke - Mi 07.12.11 22:54
HelgeLange hat folgendes geschrieben : |
kleiner Tipp wegen der Variable, es geht auch IsDebuggerPresent als Bedingung für ein Repeat-Until. |
Auch eine Idee, ich habe das bisher immer manuell gemacht. :zustimm:
HelgeLange hat folgendes geschrieben : |
Jetzt installiere ich mal alles auf der VM und teste dort. |
Es reicht dort denke ich den Remotedebugger zu installieren bzw. zu kopieren. Wenn der als Admin gestartet wird, sollte das auch gehen.
bummi - Mi 07.12.11 23:01
Nur so am Rande , ist auf dem Rechner AVG am laufen, der bringt bei Verwendung von IsDebuggerPresent unter nicht nachvollziehbaren Konstellationen Fehlermeldungen(Warnungen) und Sperren.
HelgeLange - Mi 07.12.11 23:58
HelgeLange hat folgendes geschrieben : |
Jetzt installiere ich mal alles auf der VM und teste dort. |
Es reicht dort denke ich den Remotedebugger zu installieren bzw. zu kopieren. Wenn der als Admin gestartet wird, sollte das auch gehen.[/quote]
jo, sind ja nur 3 Komponenten-Pakete, die sind schnell installiert. Ausserdem bin ich gleichmal so forsch und teste das gleich mit Delphi 2007 statt mit XE, da die Client-Anwendung ja auch in Delphi 2007 geschrieben ist und es ein rumgemache ist mit UniCode und AnsiCode in der Kommunikation.
@Bummi : AVG ? Igitt... nee, VM immer ohne antivirus, damit surfe ich ned
HelgeLange - Do 08.12.11 00:43
So, habe jetzt einfach mal ALLES aus der unit rausgenommen und in Datenmodul gepackt und rufe jetzt nur noch in ServiceStart/Stop das Datemodul auf.
Hier der Auszug :
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37:
| procedure TSIERP_WXService.ServiceCreate(Sender: TObject); begin DMM := nil; end;
procedure TSIERP_WXService.ServiceDestroy(Sender: TObject); begin LogToFile('TSIERP_WXService.ServiceDestroy'); end;
procedure TSIERP_WXService.ServiceExecute(Sender: TService); begin While Not Terminated Do ServiceThread.ProcessRequests(True); end;
procedure TSIERP_WXService.ServiceStart(Sender: TService; var Started: Boolean); begin Try DMM := TDMM.Create(nil); LogToFile('TSIERP_WXService.ServiceCreate'); Except on E: Exception do LogToFile(E.Message); End; Started := DMM.StartService; end;
procedure TSIERP_WXService.ServiceStop(Sender: TService; var Stopped: Boolean); begin Stopped := DMM.StopService; DMM.Free; DMM := nil; end; |
und das läuft, sogar in Delphi 2007. Vorher lief es nicht, und das debuggen machte Probleme, weil wenn man in ServiceCreate oder ServiceStart so durch-stepped, dann kriegt man den Timeout von Windows.
Jetzt das ganze noch unter den verschiedenen Systemen testen und dann ans TestLab wieder raus und schaun, dass die ihr OK geben.
jaenicke - Do 08.12.11 01:21
HelgeLange hat folgendes geschrieben : |
Vorher lief es nicht, und das debuggen machte Probleme, weil wenn man in ServiceCreate oder ServiceStart so durch-stepped, dann kriegt man den Timeout von Windows. |
Du müsstest da ja gar nicht durchsteppen. Es geht ja nur darum, dass du verbunden bist bevor der Dienststart weitergeht. Wenn dann eine Exception auftritt, landet die im Debugger. ;-)
HelgeLange - Do 08.12.11 01:52
genau das ist jetzt passiert und ich habe eine kleine exception bekommen, aber es wundert mich, dass dies auf einigen Rechnern lief, auf anderen nicht. Und ich hatte es in einem Try..Except block und das hat nicht geholfen.
HelgeLange - Fr 09.12.11 00:32
So zum schnellen informativen update mit den Tücken des Services...
ok, heut morgen wollte ich die Tests machen auf verschiedenen Systemen und gleich beim ersten die gleichen Probleme wie vorher :(
Habe dann dort Delphi installiert um mal zu schaun, was er dort hat, hab den Service auf das Entwicklungsverzeichnis uminstalliert. Auf einmal ging es. Dann den Service deinstalliert, einen neuen Installer gebaut, Delphi und BPL Verzeichnisse unzugänglich gemacht. Und es ging wieder nicht. Alle BPLs ins Verzeichnis des Services kopiert, kein Erfolg. Konnte dort nichtmal debuggen, kam zwar in ServiceCreate, aber danach war Schluss.
Um eine Lange Geschichte von 8 Stunden Suchen und probieren kurz zu machen : Es blieben 2 Möglichkeiten
1.) Er versucht auf einen Entwicklungspfad zuzugreifen (unwahrscheinlich, das prüfte ich)
2.) Installationsmethode.
Zu 2. muss man sagen, dass es 2 Möglichkeiten gibt einen Delphi Service zu installieren. "<Programmname>.exe / install" oder "SC.exe CREATE <ServiceName.exe> binPath= "<Pfad>\ServiceName.exe"" im command prompt mit admin.
Nun habe ich halt festgestellt, dass ich beim rumprobieren immer erstere Variante genommen habe (schneller zu schreiben :D), aber im installer die SC variante. Und die ging scheinbar nicht. Habe es mal per Hand probiert, Service installiert mit beiden Methoden und es ging nur mit der 1. Variante.
Hab dann den Installer umgeschrieben und gleich beim 1. Versuch alles geklappt.
jaenicke - Fr 09.12.11 06:43
Ein Unterschied zwischen deinen beiden Methoden, der mir direkt auffällt, ist, dass du als Name für den Dienst (der z.B. im Dienstmanager angezeigt wird) den Namen der Exe nimmst. Wenn du das nicht manuell in Delphi auch so eingestellt hast, heißt der dort anders.
Ich habe aber glaube ich für einen Delphidienst noch nie die sc.exe zur Installation benutzt, das werde ich bei Gelegenheit mal testen. ;-)
baka0815 - Fr 09.12.11 12:38
Auf jeden Fall wird die ServiceAfterInstall-Funktion nur beim Aufruf über <EXE> /install aufgerufen und nicht über die sc.exe.
HelgeLange - Fr 09.12.11 17:24
Gibt es eigentlich eine Möglichkeit, den Dienst zu starten per Kommando-Zeile ? Sowas wie <MyService>.exe /start ?
bummi - Fr 09.12.11 17:41
net start dienstname
SC Start Dienstname
Alles immer mit Adminrechten wenn UAC aktiviert
wenn Du selbst was schreiben willst:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| implementation uses WinSvc; {$R *.dfm}
procedure TForm2.Button1Click(Sender: TObject); var ss:SERVICE_STATUS; V_SC_HANDLE:SC_HANDLE; V_SC_HANDLE2:SC_HANDLE; PC:PChar; begin PC :=''; V_SC_HANDLE:=OpenSCManager(nil,nil,SC_MANAGER_ALL_ACCESS); V_SC_HANDLE2:=OpenService(V_SC_HANDLE,'DEIN_SERVICE_NAME',SERVICE_START); StartService(V_SC_HANDLE2,0,PC); CloseServiceHandle(V_SC_HANDLE2); CloseServiceHandle(V_SC_HANDLE); end; |
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!