![]() |
Alles in einem: Service und Formularanwendung
Hallo Delphigemeinde,
Habe folgendes Problem, auf das ich beim Suchen im Internet keine passende Lösung gefunden habe, weil es scheinbar recht unüblich oder eventuell un möglich ist :-D. Mein Vorhaben grundsätzlich: Ich habe eine Formularanwendung und einen Service geschrieben. Beide laufen wie erwünscht. Da kam mir der Gedanke, dass ich nicht 2 Executables haben möchte sondern nur EINE. Nun musste ich mir einen Weg überlegen, wie ich es schaffe, dass immer der richtige "Programmteil" gestartet wird. Meine Lösung: Das Programm erzeugt, wenn es als Service gestartet wird ein Mutex. Dieses Mutex frage ich immer beim Start des Programms ab und starte, wenn das Mutex bereits existiert, den "Formularteil", andernfalls den "Serviceteil". Ich gehe davon aus dass der Service IMMER vor dem Programm installiert/gestartet wird! (sonst klappts ja nicht) Zum Problem: :-P Der Service wird erfolgreich installiert über "dasprogramm.exe -install", aber er kann nicht gestartet werden. Fehlermeldung: "Der Dienst ServiceXYZ kann nicht auf "Lokaler Computer" gestartet werden. Fehler 1053: Der Dienst antwortete nicht rechtzeitig auf die Start- oder Steuerungsanforderung" Meine Frage: Was muss ich ändern damit das klappt, wie es soll? Wie gesagt ... in getrennten EXE-Dateien laufen die 2 Programme, was bedeutet, dass in den anderen units KEINE FEHLER sein können!!! Vielen Dank im Vorraus! c20c Jetzt die paar Codeschnippsel: (vereinfacht, da ansonsten alles viel zu unübersichtlich wird) dasprogramm.dpr
Delphi-Quellcode:
uses
Windows, SysUtils, m_service in 'm_service.pas', m_application in 'm_application.pas' c_program in 'c_program.pas', c_network in 'c_network.pas', u_methods in 'u_methods.pas', ... {$R *.res} const INVALID_HANDLE=0; begin if CreateMutex(nil, false, 'ServiceXYZMutex') = INVALID_HANDLE then startas_client else startas_service; end. m_application.pas (startas_client)
Delphi-Quellcode:
m_service.pas (startas_service)
unit m_application;
interface procedure startas_client; implementation uses Windows, SysUtils, Forms, //NEEDED FOR CLIENT c_program, f_main, f_lock, f_1ststart, f_overlay, f_settings, f_password, c_watcher, m_objects, const INVALID_HANDLE=0; procedure startas_client; begin Application.Initialize; Application.MainFormOnTaskbar := False; Application.Title := 'TimeControl 6.003'; Application.CreateForm(TMainForm, MainForm); Application.CreateForm(TOverlayForm, OverlayForm); ... Application.Run; end; end.
Delphi-Quellcode:
unit m_service;
interface procedure startas_service; implementation uses SvcMgr, f_service; procedure startas_service; begin if not Application.DelayInitialize or Application.Installing then Application.Initialize; Application.CreateForm(TTimeControl6Service, TimeControl6Service); Application.Run; end; end. |
AW: Alles in einem: Service und Formularanwendung
Sicher daß auch der Service-Teil anläuft, wenn du es versuchst als Service zu starten?
Mach es besser über Parameter. wenn param(1) = '-service' '-install' '-deinstall' oder sonstwas in der Art, dann als Service starten oder notfalls auch einfach nur
Delphi-Quellcode:
und den Service dann über den Parameter "-service" starten lassen
if ParamCount > 0 then service else programm;
|
AW: Alles in einem: Service und Formularanwendung
Danke für die flotte Rückmeldung! Ich hab gewusst, ich kann mich auf DP verlassen xD
Also ich hab auch -install und -uninstall als Kriterium drin, habs aber unter anderem rausgeschnitten. Das Dumme ist ja, das nicht ich den Service starte, sondern der ServiceManager von Windows. Und dem kann cih ja nicht sagen, dass er bestimmte Parameter zum Starten des Services anhängen muss, oder? Es scheint, alsob die Controlmessage vom SVCMangager an die Service-Instanz nicht ankommen würde. Oder gehe ich da jetzt einem Trugschluss auf den Leim. |
AW: Alles in einem: Service und Formularanwendung
Von welchem Betriebssystem reden wir eigentlich?
|
AW: Alles in einem: Service und Formularanwendung
im moment windows 7 x64
aber mir wäre abwärtskampatibilität bis xp lieb |
AW: Alles in einem: Service und Formularanwendung
Kann es sein, dass der Servicemanager das Fenster im Code findet deswegen den Start des Services verweigert, weil er es für einen interaktiven Service hält?
|
AW: Alles in einem: Service und Formularanwendung
Der ServiceManager nimmt auch nur die Einträge aus der Registry zum Starten und ich weiß daß dort Parameter mit angegeben werden können ... jedenfalls laufen auch einige windowseigene Services, welche mit Parametern gestartet werden.
da wäre z.B. die bekannte svchost.exe, welche mehrere Sachen, in jeweils eigenen Instanzen ausführt. wie z.B. die DNS-Cache
Delphi-Quellcode:
C:\WINDOWS\system32\svchost.exe -k NetworkService
|
AW: Alles in einem: Service und Formularanwendung
@ himitsu ok das wäre dann eine Option. Heißt aber nicht, dass es dann klappt.
Ich denke, ich werde nochmal genau Logfile führen wann das Programm wie gestartet wird. @ Luckie also, mit folgendem "Dummy-Code" funktioniert alles, dh. daran kann es nicht liegen:
Delphi-Quellcode:
program Project4;
uses SvcMgr, Unit1 in 'Unit1.pas' {Service1: TService}, Unit3 in 'Unit3.pas' {Form3}; {$R *.RES} begin if false then createnormalform else begin if not Application.DelayInitialize or Application.Installing then Application.Initialize; Application.CreateForm(TService1, Service1); Application.Run; end; end.
Delphi-Quellcode:
unit Unit3;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs; type TForm3 = class(TForm) private { Private declarations } public { Public declarations } end; var Form3: TForm3; procedure createnormalform; implementation {$R *.dfm} procedure createnormalform; begin Application.Initialize; Application.CreateForm(TForm3,Form3); Application.Run; end; end. |
AW: Alles in einem: Service und Formularanwendung
OK ich denke ich habe den Fehler gefunden.
das mit der Logfile hätt ich mir auch vorher mal überlegen können. :roll: Der Service Teil ist beim Installieren angelaufen, aber beim Starten nicht. Fehler war einerseits eine Dusseligkeit meinerseits und andererseits siehe nächster Post. Danke vielmals trotzdem für die Hilfe! |
AW: Alles in einem: Service und Formularanwendung
Damit das hier kein Sinnlos-Thread ist, teile ich meine Erkenntnisse mit der DP-Community.
Also alles klappt nun, nach folgenden Änderungen: 1. Ein normaler Named Mutex ist auf Sessions begrenzt, dh., dass man einen Globalen Mutex setzen muss, wenn der Dienst den Mutex von einer "normalen" Anwendung sehen soll und umgekehrt. Das funktioniert mit der Namensprefix "Global\".
Delphi-Quellcode:
2. Wenn man einen Globalen Mutex "abfragen" möchte und er breits existiert, bekommt man NICHT über GetLastError den Fehler ERROR_ALREADY_EXISTS, aber das zurückgegebene Mutexhandle ist = 0(invalid).
CreateMutex(nil,false,'Global\Beispielmutex');
; Dh. dass man sollte immer beides abfragen.
Delphi-Quellcode:
Wichtig ist auch, Mutex wieder Freigeben über:
hMutex:=CreateMutex(nil, false, 'Global\Beispielmutex');
if (hMutex = INVALID_HANDLE) or(GetLastError = ERROR_ALREADY_EXISTS) then ...
Delphi-Quellcode:
ReleaseMutex(hMutex);
CloseHandle(hMutex); Wenn man statt ein Mutex lieber Startparameter verwendende möchte (wie himitsu vorgeschlagen hat), kann man diese bei folgender Funktion angeben.
Delphi-Quellcode:
Nachteil: Durch die Eigenwahl des Anzeigenamens, bzw des Servicenamens ist eine Deinstallation über "C:\BeispielService.exe -uninstall" nicht mehr möglich. (logischerweise)
CreateService( SCM,
PWideChar('TCTRL6S01'), PWideChar('TCTRL6Service'), SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, 'C:\BeispielService.exe Parameter1 Parameter2', //usw nil, nil, nil, nil, nil); Abhilfe siehe:
Delphi-Quellcode:
OpenService();
DeleteService(); Ein Per-Hand-Installieren wird aber dem entsprechend schwierig, weil der von Delphi "vorkonstuierte" tService beim Installieren keine Parameter einfügt. Folglich hat man 2 Möglichkeiten: Entweder eine eigene Klasse von tService ableiten und die Installationsroutine anpassen, oder in der Registry bestimmte Einträge abändern. Zum Abschluss noch ein Kommentar: DP ist genial. Ich profitiere immer wieder von den Threads. Es wäre aber genial, wenn der letzte Post die wichtigsten für das Thema relevanten Erkenntnisse aufführt. (so wie dieser :D) Ahoi c20c |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:10 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz