AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Windows Dienst starten und beenden, interval
Thema durchsuchen
Ansicht
Themen-Optionen

Windows Dienst starten und beenden, interval

Ein Thema von TUX_der_Pinguin · begonnen am 6. Nov 2007 · letzter Beitrag vom 8. Nov 2007
Antwort Antwort
TUX_der_Pinguin

Registriert seit: 1. Jun 2005
Ort: Anholt (NRW)
608 Beiträge
 
Delphi 11 Alexandria
 
#1

Windows Dienst starten und beenden, interval

  Alt 6. Nov 2007, 15:07
Hallo,

ich habe anhand diverser Beiträge hier aus dem Forum mal einen eigenen Dienst/Service für Windows XP geschrieben,
soweit so gut klappt auch alles. Ich installiere den Dienst per Dienst.exe /install und starten tu ich im moment
noch per Verwaltung -> Dienste -> Rechts klick auf meinen Dienst -> starten.

Jetzt kommen 2 Fragen auf, wie starte ich den Dienst direkt weil beim installieren ist dieser ja noch nicht
gestartet ?! Ich bin am überlegen ein batch script oder programm im Autostart oder der gleichen zu hinterlegen
was mir meinen Dienst startet oder wenn möglich den Dienst direkt dort einfügen.

Das zweite Problem, gehe ich jetzt in die Dienstverwaltung und klicke auf Beenden erhalte ich eine Fehlermeldung,
das der Dienst nicht korrekt beendet werden konnte usw.

Hier mal der Quelltext zu meinem Dienst, der Dienst ist mit Turbo Delphi Explorer erstellt worden.
Delphi-Quellcode:
unit uMain;

interface

Const
  DelayTime = 5; //Zeitinterval in minuten
  DIR_MESSANZ = '\\server2\daten_public\daten\mess_anz\';
  FILE_LOG = 'D:\Source\Projekte\Dienst\service.log';
  MOD_Sys = 'Service';
  MOD_MessAnz = 'Mess_Anz';

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,
  DBXpress, WideStrings, DB, SqlExpr, uTools, MD5;

type
  TService1 = class(TService)
    SQLCon: TSQLConnection;
    procedure ServiceExecute(Sender: TService);
  private
    { Private-Deklarationen }
    procedure pUpdateMessAnz;
    procedure pLog(Modul, strMsg: String);
  public
    function GetServiceController: TServiceController; override;
    { Public-Deklarationen }
  end;

var
  Service1: TService1;

implementation


{$R *.DFM}





procedure ServiceController(CtrlCode: DWord); stdcall;
begin
  Service1.Controller(CtrlCode);
end;





function TService1.GetServiceController: TServiceController;
begin
  Result := ServiceController;
end;





procedure TService1.ServiceExecute(Sender: TService);
begin
  While NOT Terminated Do Begin
    ServiceThread.ProcessRequests(False);

    //Datenbank verbindung öffnen
    If NOT SQLCon.Connected Then Begin
      Try
        SQLCon.Open;
      Except
        On E: Exception Do Begin
          pLog(MOD_Sys, 'Fehler beim Verbinden mit der Datenbank!');
          pLog(MOD_Sys, E.Message);
        End;
      End;
    End;

    //Update Routinen ausführen...
    If SQLCon.Connected Then Begin
      pLog(MOD_Sys, 'Beginne Update');

      pUpdateMessAnz;
    End;{if}

    //Verbindung beenden falls noch offen...
    If SQLCon.Connected Then SQLCon.Close;

    //Service schlafen legen ...
    Sleep(1000 * 60 * DelayTime);
  End;{while}

end;





procedure TService1.pUpdateMessAnz;
begin
  //mySQL Datenbank update...
end;





procedure TService1.pLog(Modul, strMsg: string);
var
  FHandle : Text;

begin
  System.Assign(FHandle, FILE_LOG);
  {$I-}
  If FileExists(FILE_LOG) Then
    Append(FHandle)
  Else
    Rewrite(FHandle);
  {$I+}
  If IoResult = 0 Then Begin
    Writeln(FHandle, DateTimeToStr(Now)+' '+Modul+': '+strMsg);
    System.Close(FHandle);
  End;{if}

end;





end.
Was der Dienst einfach machen soll ist alle paar Minuten alle Dateien aus einem Verzeichnis prüfen ob deren Inhalt
in einer Datenbank eingetragen ist. Mir scheint es da ein Problem mit der Sleep() Anweisung zu geben jedoch wüßte
ich grade keine alternative wie ich es schaffe das der Dienst nur alle paar minuten prüft und nicht in einem durch.

mfg

TUX
  Mit Zitat antworten Zitat
Benutzerbild von GuenterS
GuenterS

Registriert seit: 3. Mai 2004
Ort: Österreich > Bad Vöslau
760 Beiträge
 
Turbo Delphi für Win32
 
#2

Re: Windows Dienst starten und beenden, interval

  Alt 6. Nov 2007, 15:53
Du könntest einen Timer verwenden ... stehe beim Beenden aber vor dem selben Problem, muss den Dienst immer durch Taskmanager oder Prozess-Explorer killen.


[Nachtrag]

Die Lösung des Problems findest Du hier:
Service-Beenden

[/Nachtrag]

[Nachtrag2]
Kein roter Kasten.
[/Nachtrag2]
Günter
Pünktlichkeit ist die Fähigkeit vorherzusagen um wieviel sich der Andere verspäten wird.
  Mit Zitat antworten Zitat
Benutzerbild von Phoenix
Phoenix
(Moderator)

Registriert seit: 25. Jun 2002
Ort: Hausach
7.606 Beiträge
 
#3

Re: Windows Dienst starten und beenden, interval

  Alt 6. Nov 2007, 16:02
Setze nach dem Beenden mal den ServiceState (oder war's nur State? man, ist schon lange her) mal auf 'Stopped'. Dann sollte zumindest der Fehler beim Beenden nicht mehr kommen.
Sebastian Gingter
Phoenix - 不死鳥, Microsoft MVP, Rettungshundeführer
Über mich: Sebastian Gingter @ Thinktecture Mein Blog: https://gingter.org
  Mit Zitat antworten Zitat
TUX_der_Pinguin

Registriert seit: 1. Jun 2005
Ort: Anholt (NRW)
608 Beiträge
 
Delphi 11 Alexandria
 
#4

Re: Windows Dienst starten und beenden, interval

  Alt 7. Nov 2007, 07:41
Verwende ich wie in dem Beitrag auf den GuenterS verwiesen hat eine der Prozeduren
OnStart bzw. OnStop dann erhalte ich eine Fehlermeldung beim Starten, siehe Anlage
laufen tut der Dienst zwar aber nur einmal danach ist er nicht mehr gestartet ...

Marabu hat zwar auch in dem Beitrag geschrieben das es gehen müßte ...
Delphi-Quellcode:
procedure TObserver.ServiceExecute(Sender: TService);
begin
  Log('Guardian executing');
  while Active do
  begin
    Sleep(1000);
    if Abs(Now - LastCheck) > Interval then
    begin
      CheckTargetService(ServiceName);
      LastCheck := Now;
    end;
    ServiceThread.ProcessRequests(false);
  end;
end;
Jedoch weiß ich nicht wo und wie man dann Active wieder auf False setzt, im OnStop
Ereignis bekommt man ja wieder den gleichen Fehler.

Gibt es den nirgendwo ein Beispiel Gerüst wo man eigentlich nur noch seine Prozeduren
einfügen muß, dann könnte ich mal sehen wie es funktioniert.

Ich hab noch folgendes gefunden was ich mir mal ansehen werde Link
Miniaturansicht angehängter Grafiken
start_error_127.jpg  
  Mit Zitat antworten Zitat
Benutzerbild von GuenterS
GuenterS

Registriert seit: 3. Mai 2004
Ort: Österreich > Bad Vöslau
760 Beiträge
 
Turbo Delphi für Win32
 
#5

Re: Windows Dienst starten und beenden, interval

  Alt 7. Nov 2007, 09:27
Das mit dem Service geht mir leider genauso. Der Thread wird zwar gestartet, aber leider wird der Dienst sofort wieder beendet. ICh könnte zwar mittels WaitFor eintragen, aber ob das mit der Steuerung dann besser geht?
Günter
Pünktlichkeit ist die Fähigkeit vorherzusagen um wieviel sich der Andere verspäten wird.
  Mit Zitat antworten Zitat
TUX_der_Pinguin

Registriert seit: 1. Jun 2005
Ort: Anholt (NRW)
608 Beiträge
 
Delphi 11 Alexandria
 
#6

Re: Windows Dienst starten und beenden, interval

  Alt 7. Nov 2007, 13:43
So ich glaub ich hab jetzt alles, ich kann meinen Service starten, beenden und sogar anhalten ohne
irgendwelche Fehlermeldungen zu bekommen.

Delphi-Quellcode:
unit uMain;
             
interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,
  ExtCtrls, DBXpress, WideStrings, DB, SqlExpr;

type
  TSvc = class(TService)
    Timer: TTimer;
    SQLCon: TSQLConnection;
    procedure ServiceContinue(Sender: TService; var Continued: Boolean);
    procedure ServiceExecute(Sender: TService);
    procedure ServicePause(Sender: TService; var Paused: Boolean);
    procedure ServiceStart(Sender: TService; var Started: Boolean);
    procedure ServiceStop(Sender: TService; var Stopped: Boolean);
    procedure TimerTimer(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    function GetServiceController: TServiceController; override;
    { Public-Deklarationen }
  end;

var
  Svc: TSvc;

implementation

uses uGlobal, uHandling_File, uHandling_Updates;

{$R *.DFM}



procedure ServiceController(CtrlCode: DWord); stdcall;
begin
  Svc.Controller(CtrlCode);
end;



function TSvc.GetServiceController: TServiceController;
begin
  Result := ServiceController;
end;



procedure TSvc.ServiceContinue(Sender: TService; var Continued: Boolean);
begin
  Continued := True;
end;



procedure TSvc.ServiceExecute(Sender: TService);
begin
  //Service läuft die ganze Zeit und Wartet auf Anfragen... False ergibt 100% Auslastung, True nicht
  While NOT Terminated Do Begin
    ServiceThread.ProcessRequests(True);
  End;{while}

end;



procedure TSvc.ServicePause(Sender: TService; var Paused: Boolean);
begin
  Paused := True;
end;



procedure TSvc.ServiceStart(Sender: TService; var Started: Boolean);
begin
  Started := True;
  Timer.Interval := 1000;
  Timer.Enabled := True;

  pLog(True, MOD_SYS, 'Service wird gestartet...');
end;



procedure TSvc.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  Stopped := True;

  pLog(True, MOD_SYS, 'Service wird beendet...');
end;



procedure TSvc.TimerTimer(Sender: TObject);
begin
  //Timer für die Zeit der verarbeitung abschalten
  Timer.Enabled := False;

  //Timer Interval setzen...
  Timer.Interval := 1000 * 60 * DelayTime;

  //Datenbank verbindung öffnen
  If NOT SQLCon.Connected Then Begin
    Try
      SQLCon.Open;
    Except
      On E: Exception Do Begin
        pLog(True, MOD_Sys, 'Fehler beim Verbinden mit der Datenbank!');
        pLog(True, MOD_Sys, E.Message);
      End;{on}
    End;{try}
  End;{if}

  If SQLCon.Connected Then Begin
    //Update Routinen ausführen...
    pUpdateMessAnz;

    //Verbindung beenden falls noch offen...
    SQLCon.Close;
  End;{if}

  //Timer wieder einschalten
  Timer.Enabled := True;

end;

end.
Desweiteren habe ich in meiner pUpdateMessAnz Prozedure eine Repeat Until schleife die auch auf den Status reagiert,
sonst läuft die Schleife weiter obwohl man den Dienst beendet bzw. angehalten hat.

Delphi-Quellcode:
procedure pUpdateMessAnz;
begin
  If SysUtils.FindFirst(DIR_MESSANZ+'????????.??M', faAnyFile, FileInfo) = 0 Then Begin
    Repeat
      //..
    Until (SysUtils.FindNext(FileInfo) <> 0) Or (Svc.Status <> csRunning);

    SysUtils.FindClose(FileInfo);
  End;{if}

end;
Was ich mir jetzt noch einfallen lassen muß wie ich den Service gestartet bekomme .. vielleicht direkt beim installieren
oder von einem Ext. Programm oder Batch script ('net start service_name') .. mal schauen.
  Mit Zitat antworten Zitat
Benutzerbild von GuenterS
GuenterS

Registriert seit: 3. Mai 2004
Ort: Österreich > Bad Vöslau
760 Beiträge
 
Turbo Delphi für Win32
 
#7

Re: Windows Dienst starten und beenden, interval

  Alt 7. Nov 2007, 14:16
Fürs starten könntest Du die Startart von manual auf automatic stellen.
Günter
Pünktlichkeit ist die Fähigkeit vorherzusagen um wieviel sich der Andere verspäten wird.
  Mit Zitat antworten Zitat
TUX_der_Pinguin

Registriert seit: 1. Jun 2005
Ort: Anholt (NRW)
608 Beiträge
 
Delphi 11 Alexandria
 
#8

Re: Windows Dienst starten und beenden, interval

  Alt 7. Nov 2007, 14:43
Ich habe folgendes eingestellt...

ServiceType = stWin32
StartType = stAuto

Wenn ich das so stehen habe brauche ich nur in der Diensteverwaltung auf meinen Dienst mit
der rechten Maustaste klicken und Starten wählen. Ich muß mal testen was die einzelnen
einstellungen bedeuten, evtl. StartType auf stBoot stellen.
  Mit Zitat antworten Zitat
Benutzerbild von GuenterS
GuenterS

Registriert seit: 3. Mai 2004
Ort: Österreich > Bad Vöslau
760 Beiträge
 
Turbo Delphi für Win32
 
#9

Re: Windows Dienst starten und beenden, interval

  Alt 7. Nov 2007, 20:39
Das kannst Du doch auch schon wenn Startart Manuell ist ? *grübel*
Günter
Pünktlichkeit ist die Fähigkeit vorherzusagen um wieviel sich der Andere verspäten wird.
  Mit Zitat antworten Zitat
TUX_der_Pinguin

Registriert seit: 1. Jun 2005
Ort: Anholt (NRW)
608 Beiträge
 
Delphi 11 Alexandria
 
#10

Re: Windows Dienst starten und beenden, interval

  Alt 8. Nov 2007, 07:45
Was ich mit der aktion erreichen will ist das ich wissen will ob allein durch
Service.exe /install der Dienst nicht nur installiert wird sondern auch gleichzeitig
gestartet werden kann oder ist dies nicht möglich so das ich so oder so
noch ein weiters programm benötige was dies erledigt oder ich das von hand
per Dienstverwaltung erledige.

Nachtrag:
Ich habe einen Beitrag gefunden, darin steht das nicht funktioniert, naja war auch mehr nur eine wissens
Frage. Ich werde das manuell starten, da der Dienst eh nur für mich ist brauche ich auch keinen komfort.
  Mit Zitat antworten Zitat
Antwort Antwort


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 02:51 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz