![]() |
Windowsdienst mit Delphi starten
Liebes Forum,
ich habe nun eine Anwendung fertig, die mit MySQL - DatenbankTabellen umgeht. Funktioniert soweit auch ganz ok. Ich würde nun gerne den Dienst: 'MySQL' starten, wenn meine Anwendung gestartet wurde und ebenso diesen Dienst wieder beenden, wenn meine Anwendung beendet wird. Wie muss ich an das Thema am besten herangehen? |
Re: Windowsdienst mit Delphi starten
Zitat:
Delphi-Quellcode:
lg. Astatunit utils; interface uses windows, SysUtils, classes, WinSvc; function ServiceGetStatus(szMachine, szService: PChar): DWORD; function ServiceRunning(szMachine, szService: PChar): Boolean; function ServiceStart(szMachine, szServiceName: PChar; ServiceArgVectors: array of PChar): Boolean; function ServiceStop(szMachine, szServiceName: PChar; Timeout: DWORD = 60000): Boolean; function ServiceRegister(szMachine, szServiceFile, szServiceName, szDisplayName: PChar): Boolean; function ServiceUnRegister(szMachine, szServiceName: PChar): Boolean; implementation {*------------------------------------------------------------------------------ Function zur Ermittlung eines Service Status @param szMachine PChar Name des Zielcomputers @param szService PChar Name des Services @return -1 = ERROR @return 1 = SERVICE_STOPPED @return 2 = SERVICE_START_PENDING @return 3 = SERVICE_STOP_PENDING @return 4 = SERVICE_RUNNING @return 5 = SERVICE_CONTINUE_PENDING @return 6 = SERVICE_PAUSE_PENDING @return 7 = SERVICE_PAUSED -------------------------------------------------------------------------------} function ServiceGetStatus(szMachine, szService: PChar): DWORD; var SCManHandle, SvcHandle: SC_Handle; SS: TServiceStatus; dwStat: DWORD; begin dwStat := 0; SCManHandle := OpenSCManager(szMachine, nil, SC_MANAGER_CONNECT); if (SCManHandle > 0) then begin SvcHandle := OpenService(SCManHandle, szService, SERVICE_QUERY_STATUS); if (SvcHandle > 0) then begin if (QueryServiceStatus(SvcHandle, SS)) then dwStat := ss.dwCurrentState; CloseServiceHandle(SvcHandle); end; CloseServiceHandle(SCManHandle); end; Result := dwStat; end; function ServiceRunning(szMachine, szService: PChar): Boolean; begin Result := SERVICE_RUNNING = ServiceGetStatus(szMachine, szService); end; // szMachine ist UNC path oder nil wenn local machine function ServiceStart(szMachine, szServiceName: PChar; ServiceArgVectors: array of PChar): Boolean; var h_manager, h_svc: SC_Handle; ServiceStatus: TServiceStatus; dwCheckPoint: DWORD; szServiceArgVectors: PPChar; begin h_manager := OpenSCManager(szMachine, nil, SC_MANAGER_CONNECT); if h_manager > 0 then begin h_svc := OpenService(h_manager, szServiceName, SERVICE_START or SERVICE_QUERY_STATUS or SC_MANAGER_ALL_ACCESS); if h_svc > 0 then begin szServiceArgVectors := nil; if Length(ServiceArgVectors) > 0 then szServiceArgVectors := @ServiceArgVectors[0]; if (StartService(h_svc, Length(ServiceArgVectors), szServiceArgVectors^)) then begin if (QueryServiceStatus(h_svc, ServiceStatus)) then begin while (SERVICE_RUNNING <> ServiceStatus.dwCurrentState) do begin dwCheckPoint := ServiceStatus.dwCheckPoint; Sleep(ServiceStatus.dwWaitHint); if (not QueryServiceStatus(h_svc, ServiceStatus)) then break; if (ServiceStatus.dwCheckPoint < dwCheckPoint) then break; end; end; end; CloseServiceHandle(h_svc); end; CloseServiceHandle(h_manager); end; Result := (SERVICE_RUNNING = ServiceStatus.dwCurrentState); end; // szMachine ist UNC path oder nil wenn local machine function ServiceStop(szMachine, szServiceName: PChar; Timeout: DWORD = 60000): Boolean; var h_manager, h_svc: SC_Handle; ServiceStatus: TServiceStatus; dwCheckPoint: DWORD; dwStart: DWORD; begin h_manager := OpenSCManager(szMachine, nil, SC_MANAGER_CONNECT); if h_manager > 0 then begin h_svc := OpenService(h_manager, szServiceName, SERVICE_STOP or SERVICE_QUERY_STATUS); if h_svc > 0 then begin if (ControlService(h_svc, SERVICE_CONTROL_STOP, ServiceStatus)) then begin if (QueryServiceStatus(h_svc, ServiceStatus)) then begin dwStart := GetTickCount; while (SERVICE_STOPPED <> ServiceStatus.dwCurrentState) do begin dwCheckPoint := ServiceStatus.dwCheckPoint; Sleep(ServiceStatus.dwWaitHint); if (not QueryServiceStatus(h_svc, ServiceStatus)) then break; if (ServiceStatus.dwCheckPoint < dwCheckPoint) then break; if GetTickCount - dwStart > Timeout then break; end; end; end; CloseServiceHandle(h_svc); end; CloseServiceHandle(h_manager); end; Result := (SERVICE_STOPPED = ServiceStatus.dwCurrentState); end; function ServiceRegister(szMachine, szServiceFile, szServiceName, szDisplayName: PChar): Boolean; var h_manager, h_svc: SC_Handle; begin Result := false; h_manager := OpenSCManager(szMachine, nil, SC_MANAGER_ALL_ACCESS); if h_manager > 0 then begin h_svc := CreateService(h_manager, szServiceName, szDisplayName, SERVICE_START or SERVICE_QUERY_STATUS or _DELETE, SERVICE_WIN32_OWN_PROCESS, // or SERVICE_INTERACTIVE_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, szServiceFile, nil, nil, nil, nil, nil); if h_svc > 0 then begin result := true; CloseServiceHandle(h_svc); end; CloseServiceHandle(h_manager); end; end; function ServiceUnRegister(szMachine, szServiceName: PChar): Boolean; var h_manager, h_svc: SC_Handle; begin Result := false; h_manager := OpenSCManager(szMachine, nil, SC_MANAGER_ALL_ACCESS); if h_manager > 0 then begin h_svc := OpenService(h_manager, szServiceName, SERVICE_ALL_ACCESS); if h_svc > 0 then begin result := DeleteService(h_svc); CloseServiceHandle(h_svc); end; CloseServiceHandle(h_manager); end; end; end. |
Re: Windowsdienst mit Delphi starten
@Astat, vielen Dank,
das mit dem Dienst starten klappt ja einwandfrei, aber beim Programm beenden hab ich noch son Problem. Als erstes beende ich ja alle Konnektoren usw. Dann beende ich den MySQL-Dienst. Der stoppt auch. Dann bekomme ich die Fehlermeldung 'Can't connect to MySQL-Server' Is ja auch so. Soll ja so sein, nur will ich eben die Fehlermeldung nicht. Achja und das Programm wird auch nicht geschlossen.....
Delphi-Quellcode:
procedure TMenue.BuendClick(Sender: TObject);
var st : integer; begin st:=ServiceGetStatus(PChar(PC), PChar(Dienst)); Datamodule1.CDS1.Active:=False; Datamodule1.CDS2.Active:=False; Datamodule1.SDS1.Active:=False; Datamodule1.SDS2.Active:=False; Datamodule1.DBConnect.Connected:=False; ServiceStop(nil, PChar(Dienst), 500); showmessage('Dienst wird beendet'); Sleep(500); repeat st:=ServiceGetStatus(PChar(PC), PChar(Dienst)); until st = 1; Application.Terminate; end; |
Re: Windowsdienst mit Delphi starten
Zitat:
Pro Datenbank sollte es nur eine Connection geben.
Delphi-Quellcode:
Macht das wirklich Sinn endlos auf die Beendigung des Dienstes zu warten?
repeat
st:=ServiceGetStatus(PChar(PC), PChar(Dienst)); until st = 1; Ich denke nicht. Wenn der MySQL-Dienst nicht beendet werden kann, dann wird das seine Gründe haben. Darauf zu warten ist doch sinnlos; es gibt dem Benutzer nur das Gefühl dass dein Programm sich aufgehängt hat. |
Re: Windowsdienst mit Delphi starten
Zitat:
es gibt nur einen.... Ich glaube ich werde es anders machen. Den Dienst auf mauell umstellen, beim Programmstart dann den Dienst starten und dann wenn das Programm beendet wird, den Dienst einfach weiter laufen lassen..... |
Re: Windowsdienst mit Delphi starten
Ich glaube nicht, dass das gehen wird. Zum Dienst starten werden erhöhte Rechte benötigt. Diese hat kein User und somit auch nicht dein Programm.
Du solltest eine Embedded-Variante nutzen, welche du mit einer DLL einbinden kannst. Alternativ kannst du den Mysql im Usercontext starten. Allerdings geht das nicht als einen Dienst. |
Re: Windowsdienst mit Delphi starten
Bedenke auch das wenn dein Programm verkaufst und es nicht OpenSource ist das du für jede Verteilung eine MySQL-Serverlizenz benötigst.
Bei Embedded auf jeden fall und bei "richigen" Server wenn du nur mit diesem Lauffähig bist. |
Re: Windowsdienst mit Delphi starten
Hinzukommt, dass dein Programm Administratorenrechte benötigt, um den Dienst zu starten und zu stoppen.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:25 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-2025 by Thomas Breitkreuz