AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Windowsdienst mit Delphi starten

Ein Thema von hirsch · begonnen am 11. Mai 2010 · letzter Beitrag vom 12. Mai 2010
Antwort Antwort
hirsch

Registriert seit: 29. Jan 2008
Ort: Tuttlingen
88 Beiträge
 
Delphi 2007 Professional
 
#1

Windowsdienst mit Delphi starten

  Alt 11. Mai 2010, 12:51
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?
Wolfgang Hirsch
  Mit Zitat antworten Zitat
Astat

Registriert seit: 2. Dez 2009
Ort: München
320 Beiträge
 
Lazarus
 
#2

Re: Windowsdienst mit Delphi starten

  Alt 11. Mai 2010, 13:03
Zitat von hirsch:
..an das Thema am besten herangehen?
Delphi-Quellcode:

unit 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.
lg. Astat
Lanthan Astat
06810110811210410503210511511603209711003210010110 9032084097103
03211611111604403209711003210010110903210010510103 2108101116122
11610103209010110510810103206711110010103210511003 2068101108112
10410503210310111509910411410510109810111003211910 5114100046
  Mit Zitat antworten Zitat
hirsch

Registriert seit: 29. Jan 2008
Ort: Tuttlingen
88 Beiträge
 
Delphi 2007 Professional
 
#3

Re: Windowsdienst mit Delphi starten

  Alt 11. Mai 2010, 15:59
@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;
Wolfgang Hirsch
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#4

Re: Windowsdienst mit Delphi starten

  Alt 11. Mai 2010, 17:00
Zitat von hirsch:
Als erstes beende ich ja alle Konnektoren usw.
Wie viele sind das denn?
Pro Datenbank sollte es nur eine Connection geben.
Delphi-Quellcode:
repeat
   st:=ServiceGetStatus(PChar(PC), PChar(Dienst));
until st = 1;
Macht das wirklich Sinn endlos auf die Beendigung des Dienstes zu warten?
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.
Andreas
  Mit Zitat antworten Zitat
hirsch

Registriert seit: 29. Jan 2008
Ort: Tuttlingen
88 Beiträge
 
Delphi 2007 Professional
 
#5

Re: Windowsdienst mit Delphi starten

  Alt 12. Mai 2010, 07:08
Zitat von hirsch:
Delphi-Quellcode:
   Datamodule1.DBConnect.Connected:=False;
   ServiceStop(nil, PChar(Dienst), 500);
Hallo Shmia,
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.....
Wolfgang Hirsch
  Mit Zitat antworten Zitat
generic

Registriert seit: 24. Mär 2004
Ort: bei Hannover
2.395 Beiträge
 
Delphi XE5 Professional
 
#6

Re: Windowsdienst mit Delphi starten

  Alt 12. Mai 2010, 08:47
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.
Coding BOTT - Video Tutorials rund um das Programmieren - https://www.youtube.com/channel/UCUG...aXLclwO9qA-lzA
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.002 Beiträge
 
Delphi 10.4 Sydney
 
#7

Re: Windowsdienst mit Delphi starten

  Alt 12. Mai 2010, 08:52
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.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie
(Moderator)

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#8

Re: Windowsdienst mit Delphi starten

  Alt 12. Mai 2010, 12:09
Hinzukommt, dass dein Programm Administratorenrechte benötigt, um den Dienst zu starten und zu stoppen.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:11 Uhr.
Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf