Hallo,
ich habe hier ein C-Programm (srvdemo.exe, geschrieben mit GCC / G++
unter Eclipse), das sich selbst als Windows-Service installieren, als
Service laufen und sich auch wieder als Service deinstallieren kann.
Jetzt bräuchte ich noch eine Möglichkeit, wie das Programm / der Service
gleich am Anfang erkennen kann, ob es / er von der Konsole
("DOS-Fenster") oder vom Windows-System aus gestartet worden ist.
Wenn Kommandozeilenparameter angegeben sind, ist das ja kein Problem,
die kann man ja z.B. mit "lpCmdLine" auswerten und in diesem Fall ist
der Start von der Konsole aus erfolgt.
Aber wie geht das, wenn das Programm / der Dienst ohne
Kommandozeilenparameter gestartet worden sind ?
Der Programmstart erfolgt mit "int WINAPI WinMain()", nicht mit "main()"
Wird der Dienst als Dienst gestartet, funktioniert die Verknüpfung mit
dem SCM per StartServiceCtrlDispatcher, die schlägt fehl, wenn der
Dienst als normales Exe-File gestartet wird.
Irgendwo in Deinem Code hast Du ein Array mit Einträgen vom Typ
SERVICE_TABLE_ENTRY, mit der Du den Einsprungpunkt für die eigentliche
Servicefunktion bekanntgibst. Diese Tabelle wird mit obiger Funktion an
den SCM übergeben, der daraufhin diese Funktion aufruft.
Der Aufruf von StartServiceCtrlDispatcher erfolgt üblicherweise in
main, bzw. müsste bei Dir in WinMain erfolgen.
PS. Die Windows-Konsole ist kein "DOS-Fenster".
Hallo,
danke, diese Möglichkeit ist mir bekannt.
Allerdings kann es relativ lange dauern, bis die Funktion
"StartServiceCtrlDispatcher()" beim Konsolenaufruf den Fehler
"ERROR_FAILED_SERVICE_CONNECT" zurückgibt.
Ich habe noch einen Hinweis auf eine andere Möglichkeit gefunden,
allerdings werde ich daraus nicht ganz schlau :
"A better way is to query the console mode for the standard output
device. When running as a service the console are not availible and this
operation will fail."
Habt ihr eine Idee, wie das funktionieren soll ?
debugger schrieb:> Jetzt bräuchte ich noch eine Möglichkeit, wie das Programm / der Service> gleich am Anfang erkennen kann, ob es / er von der Konsole> ("DOS-Fenster") oder vom Windows-System aus gestartet worden ist.
Hallo,
das sind eigentlich 2 Programmsysteme in einem: das eine ist das
Konsolenprogramm, das installiert oder deinstalliert, ganz normal wie
andere Konsolenprogramme auch. Mit dem Dienst selbst muss das nicht in
einer Datei stehen.
Der eigentliche Dienst besteht dagegen aus einer Sprungtabelle und den
zugehörigen Funktionen, die einzelnen Funktionen werden vom Windows
Service Manager aufgerufen. Dazu ist der Konsole Teil nicht nötig.
Damit erledigt sich die Frage von selbst.
Gruss Reinhard
Sorry, nein.
Es ist ein Programm, das sich als Dienst installiert, deinstalliert und
auch beim Systemaufruf als Dienst läuft, wenn es als Dienst schon
instaliert ist (das prüft es selbständig).
Zusätztlich sollte es jetzt am Programmanfang auch noch erkennen können,
ob es von der Konsole aus oder vom System aufgerufen wurde.
Eine Alternative wäre es, das Benutzerkonto festzustellen, in dem der
Prozess gestartet wird.
Das kann nur dann zu Fehlerkennungen führen, wenn Du eine Installation
auch in als normalen Konten verwendeten Benutzerkonten vorsiehst.
Früher (TM) war es so, dass die Services auf einem eigenen
Service-"Desktop" gestartet werden. Es gab eine eine API Funktion
(GetCurrentDesktop? GetCurrentWindowsStation?), mit der man das eifnach
rausfinden konnte. Ich weiss aber nicht, ob das noch immer so ist.
Letztlich geht das in die gleiche Richtung wieder das Ermitteln, in
welchem Benutzer-Kontext das Programm läuft. Services laufen ja unter
einem speziellen Konto.
Axel
Axel Heider schrieb:> Services laufen ja unter einem speziellen Konto.
Können, müssen nicht. Dienste können in beliebigen Konten laufen, sofern
diese über das Privileg "logon as service" verfügen.
Tja....dann gibt es da in der Tickkiste vielleicht noch die API
Funktionen GetConsoleScreenBufferInfo() und GetStdHandle(). Dait lässt
sich zumindest rausfinden, ob eine Konsole da ist
Axel
es geht auch noch anders, man kann den parrent von dem eigenen Prozess
ermitteln. Wenn es die service.exe ist dann ist man ein Service. Nicht
schön geht aber.
Man kann auch die Servicemanager-API benutzen um den Status abzufragen
(QueryServiceStatusEx/ControlService[Ex]).
Wenn SERVICE_START_PENDING ==> Service, sonst Konsole