AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Alles in einem: Service und Formularanwendung

Ein Thema von c20c · begonnen am 22. Jul 2010 · letzter Beitrag vom 23. Jul 2010
Antwort Antwort
c20c

Registriert seit: 23. Mai 2009
Ort: Liederbach
9 Beiträge
 
Delphi 2009 Architect
 
#1

Alles in einem: Service und Formularanwendung

  Alt 22. Jul 2010, 20:13
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 .


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:
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:
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.
m_service.pas (startas_service)
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.
Kermit the Frog
NEIN .... 22 durch 11 ist NICHT 1

Geändert von c20c (22. Jul 2010 um 20:15 Uhr) Grund: fehler entdeckt passiert, wenn man viel rausschneiden muss -.-
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.062 Beiträge
 
Delphi 12 Athens
 
#2

AW: Alles in einem: Service und Formularanwendung

  Alt 22. Jul 2010, 21:23
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 if ParamCount > 0 then service else programm; und den Service dann über den Parameter "-service" starten lassen
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
c20c

Registriert seit: 23. Mai 2009
Ort: Liederbach
9 Beiträge
 
Delphi 2009 Architect
 
#3

AW: Alles in einem: Service und Formularanwendung

  Alt 22. Jul 2010, 21:38
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.
Kermit the Frog
NEIN .... 22 durch 11 ist NICHT 1
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

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

AW: Alles in einem: Service und Formularanwendung

  Alt 22. Jul 2010, 21:48
Von welchem Betriebssystem reden wir eigentlich?
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
c20c

Registriert seit: 23. Mai 2009
Ort: Liederbach
9 Beiträge
 
Delphi 2009 Architect
 
#5

AW: Alles in einem: Service und Formularanwendung

  Alt 22. Jul 2010, 21:50
im moment windows 7 x64

aber mir wäre abwärtskampatibilität bis xp lieb
Kermit the Frog
NEIN .... 22 durch 11 ist NICHT 1
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

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

AW: Alles in einem: Service und Formularanwendung

  Alt 22. Jul 2010, 21:52
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?
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.062 Beiträge
 
Delphi 12 Athens
 
#7

AW: Alles in einem: Service und Formularanwendung

  Alt 22. Jul 2010, 21:58
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 C:\WINDOWS\system32\svchost.exe -k NetworkService
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
c20c

Registriert seit: 23. Mai 2009
Ort: Liederbach
9 Beiträge
 
Delphi 2009 Architect
 
#8

AW: Alles in einem: Service und Formularanwendung

  Alt 22. Jul 2010, 22:07
@ 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.
Kermit the Frog
NEIN .... 22 durch 11 ist NICHT 1

Geändert von c20c (22. Jul 2010 um 22:09 Uhr)
  Mit Zitat antworten Zitat
c20c

Registriert seit: 23. Mai 2009
Ort: Liederbach
9 Beiträge
 
Delphi 2009 Architect
 
#9

AW: Alles in einem: Service und Formularanwendung

  Alt 22. Jul 2010, 22:35
OK ich denke ich habe den Fehler gefunden.

das mit der Logfile hätt ich mir auch vorher mal überlegen können.
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!
Kermit the Frog
NEIN .... 22 durch 11 ist NICHT 1

Geändert von c20c (23. Jul 2010 um 13:10 Uhr)
  Mit Zitat antworten Zitat
c20c

Registriert seit: 23. Mai 2009
Ort: Liederbach
9 Beiträge
 
Delphi 2009 Architect
 
#10

AW: Alles in einem: Service und Formularanwendung

  Alt 23. Jul 2010, 12:59
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:
CreateMutex(nil,false,'Global\Beispielmutex');
;
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).
Dh. dass man sollte immer beides abfragen.
Delphi-Quellcode:
hMutex:=CreateMutex(nil, false, 'Global\Beispielmutex');
if (hMutex = INVALID_HANDLE) or(GetLastError = ERROR_ALREADY_EXISTS) then ...
Wichtig ist auch, Mutex wieder Freigeben über:
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:
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);
Nachteil: Durch die Eigenwahl des Anzeigenamens, bzw des Servicenamens ist eine Deinstallation über "C:\BeispielService.exe -uninstall" nicht mehr möglich. (logischerweise)
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 )

Ahoi c20c
Kermit the Frog
NEIN .... 22 durch 11 ist NICHT 1

Geändert von c20c (23. Jul 2010 um 13:04 Uhr)
  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 09:16 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