AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Tutorials Delphi Wie erstelle ich einen Dienst für WinNT / Win2000 / Win XP
Tutorial durchsuchen
Ansicht
Themen-Optionen

Wie erstelle ich einen Dienst für WinNT / Win2000 / Win XP

Ein Tutorial von MaBuSE · begonnen am 28. Dez 2005 · letzter Beitrag vom 21. Okt 2013
Antwort Antwort
Seite 1 von 4  1 23     Letzte »    
Benutzerbild von MaBuSE
MaBuSE
Registriert seit: 23. Sep 2002
Ich habe in dem Beitrag ISDN-Anrufmonitor eine kleine Anleitung zu Diensten geschrieben, das gehört aber eigentlich hier hin

Was ist ein Dienst?
In WinNT/Win2000/WinXP (und neuer) gibt es die Möglichkeit Programme schon beim Starten des Betriebssystems, noch bevor sich ein Benutzer anmeldet, auszuführen. Diese Programme werden als Dienste (engl: Service) bezeichnet. Diese Dienste werden über die Diensteverwaltung gesteuert.
Mit Systemsteuerung -> Verwaltung -> Dienste kommt man zur Diensteverwaltung. hier kann man sehen welche Dienste auf dem Rechner verfügbar sind. Es ist auch der Status und die Beschreibung zu sehen.
(Von der Konsole (cmd.exe) kann man mit "net start" eine Liste der gestarteten Dienste sehen.)

Wie erstellt man einen Dienst?
Unter Delphi 7 geht das ganz einfach.
(Ich habe gerade mal Delphi 5 gestartet, dort geht es auch.)
  • Menü Datei -> Neu... aufrufen.
  • In der Objektgalerie -> Neu -> Service Anwendung aufrufen.
  • Das Grundgerüst zu einem Dienst ist nun da. (Projekt1.dpr und Unit1.pas/dfm)
  • Es wird eine Unit1.pas mit dem TService namens Service1 angezeigt. (nicht visuelles Form)
  • In den Eigenschaften gibt es
    • DisplayName - Das ist der Name des Dienstes, der in der Diensteverwaltung angezeigt wird.
    • Interactive - sollte True sein und bedeutet, das der Dienst auch mit dem Benutzer interagieren darf
      (z.B. Dialogfenster, Icon in der Taskleiste (TNA), ...)
    • Dependencies - Abhängigkeiten von anderen Diensten: z.B. "Telefonie" (TAPI)
  • über die Ereignisse wird der Code ausgeführt:
    • onExecute - Das ist das Hauptereignis:
      Es wird aufgerufen wenn der Dienst ausgeführt wird. In diesem Ereignis sollte eine Schleife stehen die die Tätigkeiten des Dienstes ausführt. Benutzt Du eine Komponente (z.B. TTimer) um die Anrufe zu pollen dann z.B.
      Delphi-Quellcode:
      ...
        while not Terminated do
        begin
          ServiceThread.ProcessRequests(False);
        end;
      ...
      Wenn Du das selbst in einer Schleife macht z.B.
      Delphi-Quellcode:
      ...
        while not Terminated do
        begin
          ServiceThread.ProcessRequests(False);

          if isTelephoneCall then
          begin
            // show Infos about Call
          end;
        end;
      ...
Die Hilfe von Delphi enthält weitere Infos

Zu jedem Dienst wird ein TServiceTread ausgeführt. (Es können auch mehrere Dienste in einer Exe enthalten sein.) Sollten mehrere Dienste in einer Applikation enthalten sein muss unbedingt threadsicher programmiert werden. Der TServiceThread ist so gestaltet, dass die Funktionalität des Dienstes in der OnExecute implementiert wird. Der TServiceThread hat seine eigene Execute Methode die OnStart und OnExecute aufruft.
Delphi-Quellcode:
{*******************************************************}
{       Borland Delphi Visual Component Library         }
{       Services                                        }
{       Copyright (c) 1997,99 Inprise Corporation       }
{*******************************************************}
unit SvcMgr;
...
procedure TServiceThread.Execute;
...
    FService.Status := csStartPending;
    Started := True;
    if Assigned(FService.OnStart) then FService.OnStart(FService, Started);
    // wird Started in OnStart aud False gesetzt wird OnExecute nie aufgerufen
    if not Started then Exit;
    try
      FService.Status := csRunning;
      if Assigned(FService.OnExecute)
        then FService.OnExecute(FService) // onExecute aufrufen
        else ProcessRequests(True);
      ProcessRequests(False);
...
Da die Ausführung der OnStart / OnExecute zeit braucht kann der Thread derweil nicht auf simultane Anfragen von anderen Clients reagieren. Deshalb kann man auch einen eigenen Thread erzeugen.
Das würde dann so aussehen:
Delphi-Quellcode:
...
  TeigenerThread = class(TThread)
    public
      procedure Execute; override;
  end;
...
var
  eigenerThread: TeigenerThread;
...
procedure TeigenerThread.Execute;
begin
  while not Terminated do
  begin
    Beep;
    // Das braucht die Zeit, in der sonst der Dienst tot wäre.
    Sleep(500);
  end;
end;
...
procedure TService1.Service1Start(Sender: TService; var Started: Boolean);
begin
  eigenerThread := TeigenerThread.Create(False);
  Started := True;
end;
...
procedure TService1.Service1Continue(Sender: TService; var Continued: Boolean);
begin
  eigenerThread.Resume;
  Continued := True;
end;
...
procedure TService1.Service1Pause(Sender: TService; var Paused: Boolean);
begin
  eigenerThread.Suspend;
  Paused := True;
end;
...
procedure TService1.Service1Stop(Sender: TService; var Stopped: Boolean);
begin
  eigenerThread.Terminate;
  Stopped := True;
end;
...
Das der TeigeneThread thadtsicher programmiert werden sollte versteht sich ja von selbst.

Mein Tipp:
Schreib dir mal einen Dienst, der in jedem Ereignis nur ein ShowMessage stehen hat.
Damit kannst Du dann schnell rausbekommen wann welche Ereignisse aufgerufen werden.
z.B.
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs;

type
  TService1 = class(TService)
    procedure ServiceAfterInstall(Sender: TService);
    procedure ServiceAfterUninstall(Sender: TService);
    procedure ServiceBeforeInstall(Sender: TService);
    procedure ServiceBeforeUninstall(Sender: TService);
    procedure ServiceContinue(Sender: TService; var Continued: Boolean);
    procedure ServiceCreate(Sender: TObject);
    procedure ServiceDestroy(Sender: TObject);
    procedure ServiceExecute(Sender: TService);
    procedure ServicePause(Sender: TService; var Paused: Boolean);
    procedure ServiceShutdown(Sender: TService);
    procedure ServiceStart(Sender: TService; var Started: Boolean);
    procedure ServiceStop(Sender: TService; var Stopped: Boolean);
  private
    { Private-Deklarationen }
  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.ServiceAfterInstall(Sender: TService);
begin
  showMessage('AfterInstall');
end;

procedure TService1.ServiceAfterUninstall(Sender: TService);
begin
  showMessage('AfterUninstall');
end;

procedure TService1.ServiceBeforeInstall(Sender: TService);
begin
  showMessage('BeforeInstall');
end;

procedure TService1.ServiceBeforeUninstall(Sender: TService);
begin
  showMessage('BeforeUninstall');
end;

procedure TService1.ServiceContinue(Sender: TService;
  var Continued: Boolean);
begin
  showMessage('OnContinue');
  Continued := True;
end;

procedure TService1.ServiceCreate(Sender: TObject);
begin
  showMessage('OnCreate');
end;

procedure TService1.ServiceDestroy(Sender: TObject);
begin
  showMessage('OnDestroy');
end;

procedure TService1.ServiceExecute(Sender: TService);
begin
  showMessage('OnExecute - begin');
  while not Terminated do
  begin
    ServiceThread.ProcessRequests(False);
  end;
  showMessage('OnExecute - end');
end;

procedure TService1.ServicePause(Sender: TService; var Paused: Boolean);
begin
  showMessage('OnPause');
  Paused := True;
end;

procedure TService1.ServiceShutdown(Sender: TService);
begin
  showMessage('OnShutdown');
end;

procedure TService1.ServiceStart(Sender: TService; var Started: Boolean);
begin
  showMessage('OnStart');
  Started := True;
end;

procedure TService1.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  showMessage('OnStop');
  Stopped := True;
end;

end.
Die erzeugte Exe Datei mußt Du Mit dem Parameter INSTALL aufrufen um den Dienst zu registrieren.
Mit Projekt1.exe UNINSTALL kannst Du den Dienst wieder aus der Diesteverwaltung entfernen.

Ich hoffe das hilft Dir erst mal weiter.
(°¿°) MaBuSE - proud to be a DP member
(°¿°) MaBuSE - proud to be a "Rüsselmops" ;-)
 
Benutzerbild von Luckie
Luckie

 
Delphi 2006 Professional
 
#2
  Alt 28. Dez 2005, 10:25
Zitat von MaBuSE:
Mein Tipp:
Schreib dir mal einen Dienst, der in jedem Ereignis nur ein ShowMessage stehen hat.
Dazu muss es aber ein interaktiver Dienst sein, sonst sieht man nichts. Dienste laufen auf dem Systemkonto mit allen Rechten und dazugehörigen Privilegien des Systemkontos. Ein Dienst läuft auch in einer anderen WindowsStation und können somit nicht mit der interaktiven WindowsStation und dem Desktop des Benutzer interagieren. Erst wenn es ein interaktiver Dienst ist kann er das. Man sollte sich aber den Risiken bewußt sein, den ein interaktiver Dienst mit sich bringr. Hier zu sei auch der Artikel Shatter Attack zu empfehlen. Generell rät auch Micosoft davon ab interaktive Dienste aus sicherheits Gründen nicht zu verwenden.
Michael
  Mit Zitat antworten Zitat
Benutzerbild von mh166
mh166

 
Delphi 10.2 Tokyo Starter
 
#3
  Alt 28. Dez 2005, 10:36
Und mal als kleine Anmerkung nebenbei: die Komponenten SvCom scheinen auch nicht schlecht zu sein. Habe zwar noch nicht damit gearbeitet, aber die Webseite mal durchgeguckt. Sehr interessant ist besonders auch die Kompatibilität zu Win9X! Schade eigentlich, dass die 99$ kosten. Aber irgendwo kann ich das shcon nachvollziehen. Vielleicht hat ja schon jemand damit gearbeitet?

Ansonsten: geiles Tutorial, MaBuSE. Werd ich mal ausprobieren. Könnte ich nämlich in einem meiner nächsten Projekte vielleicht gebrauchen...

mfg, mh166
  Mit Zitat antworten Zitat
Benutzerbild von MaBuSE
MaBuSE

 
Delphi 10 Seattle Enterprise
 
#4
  Alt 28. Dez 2005, 10:50
Zitat von Luckie:
Zitat von MaBuSE:
Mein Tipp:
Schreib dir mal einen Dienst, der in jedem Ereignis nur ein ShowMessage stehen hat.
Dazu muss es aber ein interaktiver Dienst sein, sonst sieht man nichts.
Das steht auch im Tutorial:

Zitat von MaBuSE:
...
In den Eigenschaften gibt es
  • DisplayName - Das ist der Name des Dienstes, der in der Diensteverwaltung angezeigt wird.
  • Interactive - sollte True sein und bedeutet, das der Dienst auch mit dem Benutzer interagieren darf
    (z.B. Dialogfenster, Icon in der Taskleiste (TNA), ...)
...
Das sollte auf True sein bezieht sich auf den ISDN Monitor für diesen der Beitrag geschrieben wurde.

Ansonsten hat Luckie Recht
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

 
Delphi 2006 Professional
 
#5
  Alt 28. Dez 2005, 11:15
Oh, aber nichts destotrotz sollte man meine Sicherheisthinweise beachten. Eventuell kannst du noch auf Ollis nonVCL NT Service Tutorial verweisen. Die Service Vorlage gibt es nämlich erst ab der Professional Version von Delphi.

Die Links:
http://www.michael-puff.de/dirindex....orte/Assarbad/
http://assarbad.net/de/stuff
Michael
  Mit Zitat antworten Zitat
Benutzerbild von MaBuSE
MaBuSE

 
Delphi 10 Seattle Enterprise
 
#6
  Alt 28. Dez 2005, 11:45
Zitat von Luckie:
Eventuell kannst du noch auf Ollis nonVCL NT Service Tutorial verweisen.
Meinst Du das hier:Es gibt auch noch einen englischen Text von Borland zu Services:
http://info.borland.com/techpubs/del...g/buildap.html
Dort steht auch wie man Dienste debuggt.
(Ich habe den Teil mit den TeigenerThread an diesen Text angelehnt.)

Es ist auch ein Beispiel in der Hilfe von Delphi vorhanden.
Dieser Beispiel Dienst lauscht an Port 80 un loggt die Zugriffe in eine Textdatei.

In der Delphi Hilfe nach "Service-Anwendungen" suchen.
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

 
Delphi 2006 Professional
 
#7
  Alt 28. Dez 2005, 11:50
Zitat von MaBuSE:
Meinst Du das hier:
Ja, das ist da wohl.
Michael
  Mit Zitat antworten Zitat
Westcliff
 
#8
  Alt 2. Jan 2006, 14:19
Noch was kleines zum Thema:

Erstellung eines Services mittels der Delphi-Vorlage (TService) hat eigentlich prima funktioniert. Auch das installieren mit PROGRAMMNAME /install bzw. /uninstall.
Hat man allerdings den Dienst via InstallShield versucht zu installieren, hat das jedesmal einen Fehler 1053 nach sich geführt und der Dienst lies sich nicht installieren.

Hab das jetzt auf Asserbads API-Gerüst gesetzt und siehe da - nun geht es auch mit Installshield.
Hat mich dennoch ein wenig verwirrt und ich weiss noch nicht ganz, wem ich da jetz die Schuld in die Schuhe schieben soll
  Mit Zitat antworten Zitat
mimi

 
FreePascal / Lazarus
 
#9
  Alt 6. Apr 2006, 16:42
Zitat:
# Menü Datei -> Neu... aufrufen.
# In der Objektgalerie -> Neu -> Service Anwendung aufrufen.
# Das Grundgerüst zu einem Dienst ist nun da. (Projekt1.dpr und Unit1.pas/dfm)
ich finde den menupunkt bei mir nicht unter neu.... in der objektgallerie ! liegt das an d7 PE ?
Michael Springwald
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

 
Delphi 11 Alexandria
 
#10
  Alt 6. Apr 2006, 16:44
Zitat von mimi:
liegt das an d7 PE ?
Ja, Dienste gibt es in den PE-Versionen nicht. Da müsste alles vonhand gemacht werden

......
Daniel W.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 4  1 23     Letzte »    


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 10:12 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