Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi TerminateProcess geht nicht die Zweite (https://www.delphipraxis.net/160911-terminateprocess-geht-nicht-die-zweite.html)

QuickAndDirty 7. Jun 2011 15:31

TerminateProcess geht nicht die Zweite
 
Also folgender Faden hat mir nicht geholfen
http://www.delphipraxis.net/22108-te...-geht-net.html

Da wir mittlerweile einen Haufen an Diensten installieren die zum Teil auch von einander abhängig sind und je nach Datensicherungsprogramm während der Datensicherung geschlossen sein müssen liefern wir seit einiger Zeit zusätzlich einen Guard der Diese Dienste überwacht aus....

Dieser Guard managed die Laufzeit der Dienste und überwacht zusätzlich deren Funktionalität...sollte also ein Programm über einen Timeout "hängen" stoppt er den Dienst. Sollte das nicht funktionieren (Dienst nach Timeout immer noch in der Prozessliste), dann Führt er TerminateProcess aus.

Das läuft soweit auch.


Nur bei einem einzigen Kunden nicht...... :(

Da versagt Terminateprocess bei einem der Dienste...immer.

Woran kann das liegen.
Folgende "Fehlerquellen" sind bekannt:
-Prozess vom User System kann/soll mann nicht terminieren. (Ist ok, deswegen laufen alle Prozesse als Administrator)
-Prozess von einem anderen User kann/soll man nicht terminieren. (Ist ok, alle laufen im User Kontext Administrator)

Vermutung:
Im Services.msc steht der hängende Prozess als "Wird beendet.."
kann es sein das TerminateProcess nicht funktioniert während der Dienst beendet zu werden versucht?

Christian Seehase 7. Jun 2011 16:29

AW: TerminateProcess geht nicht die Zweite
 
Moin QuickAndDirty,

gibt es im Eventlog irgenwelche dazu passenden Einträge?

Dezipaitor 7. Jun 2011 16:41

AW: TerminateProcess geht nicht die Zweite
 
Wenn du ein Dienst mit Terminateprocess beendest, dann ist er weg, ohne irgendwen zu informieren. Das ist, als ob der Boden unter den Füßen weggezogen wird. D.h. der ServiceManager bekommt das selbst erst mit, wenn er denn auch danach sucht (sprich jemand aktualisiert es). Schau mal in den Eigenschaftgen im SM, ob da der Starten button wieder aktiv ist.
Außerdem kannst du mal ProcessExplorer angucken, ob der Prozess noch aktiv ist. Wenn ja, dann hast du ein anderes Problem. Wenn ein Prozess in einem nicht unterbrechbaren Interrupt fest hängt, dann kann TerminateProcess das auch nicht schneller machen.

Zacherl 8. Jun 2011 12:07

AW: TerminateProcess geht nicht die Zweite
 
Um den Service zu beenden, würde ich wie Dezipiator schon angedeutet hat, lieber direkt die Service Manager API verwenden. Auch bei normalen Prozessen ist ein TerminateProcess() zu vermeiden.

Ich hatte irgendwo mal eine Implementation gesehen, welche einfach ExitProcess() in den Zielprozess injiziert. Das ist zwar etwas umständlich, aber es gibt dem Zielprozess wenigstens Zeit, eventuelle Finalizations auszufüren.

mleyen 8. Jun 2011 12:17

AW: TerminateProcess geht nicht die Zweite
 
Zitat:

Zitat von Zacherl (Beitrag 1105241)
Ich hatte irgendwo mal eine Implementation gesehen, welche einfach ExitProcess() in den Zielprozess injiziert. Das ist zwar etwas umständlich, aber es gibt dem Zielprozess wenigstens Zeit, eventuelle Finalizations auszufüren.

http://www.delphipraxis.net/1061510-post3.html

QuickAndDirty 9. Jun 2011 10:05

AW: TerminateProcess geht nicht die Zweite
 
Zitat:

Zitat von Christian Seehase (Beitrag 1105112)
Moin QuickAndDirty,

gibt es im Eventlog irgenwelche dazu passenden Einträge?

Arg...das offensichtliche leider noch nicht geprüft, danke!

QuickAndDirty 9. Jun 2011 10:07

AW: TerminateProcess geht nicht die Zweite
 
Zitat:

Zitat von Dezipaitor (Beitrag 1105114)
Wenn du ein Dienst mit Terminateprocess beendest, dann ist er weg, ohne irgendwen zu informieren. Das ist, als ob der Boden unter den Füßen weggezogen wird. D.h. der ServiceManager bekommt das selbst erst mit, wenn er denn auch danach sucht (sprich jemand aktualisiert es). Schau mal in den Eigenschaftgen im SM, ob da der Starten button wieder aktiv ist.
Außerdem kannst du mal ProcessExplorer angucken, ob der Prozess noch aktiv ist. Wenn ja, dann hast du ein anderes Problem. Wenn ein Prozess in einem nicht unterbrechbaren Interrupt fest hängt, dann kann TerminateProcess das auch nicht schneller machen.

Der Prozess ist in der Prozessliste immernoch vorhanden...und wird permanent alle paar sekunden versucht vom Guard beendet zu werden...

Aber im in der Prozessliste (Taskmanager) kann ich ihn per Prozessbeenden stoppen.

QuickAndDirty 9. Jun 2011 10:12

AW: TerminateProcess geht nicht die Zweite
 
Zitat:

Zitat von Zacherl (Beitrag 1105241)
Um den Service zu beenden, würde ich wie Dezipiator schon angedeutet hat, lieber direkt die Service Manager API verwenden. Auch bei normalen Prozessen ist ein TerminateProcess() zu vermeiden.

Wir versuchen den Dienst regulär zu stoppen, erst wenn er nach X Sekunden dann noch als Prozess existiert eskalieren wir zu TerminateProcess.

Zitat:

Zitat von Zacherl (Beitrag 1105241)
Ich hatte irgendwo mal eine Implementation gesehen, welche einfach ExitProcess() in den Zielprozess injiziert. Das ist zwar etwas umständlich, aber es gibt dem Zielprozess wenigstens Zeit, eventuelle Finalizations auszufüren.

Sagt mir so gar nichts. sorry. ExitProcess ist der Befehl der am Ende von Application.terminate ausgeführt wird? Oder wie darf ich mir das vorstellen? (ja ich schau gleich in der Hilfe nach, no prob)


Wie sähe die Eskalationsreihenfolge also aus?
1. Stoppen des Dienstes
2. Exitprocess Injecten
3. TerminateProcess

????
aber wieso funzt Terminate Process nicht? (über 14 stunden hinweg)

CCRDude 10. Jun 2011 08:10

AW: TerminateProcess geht nicht die Zweite
 
Zitat:

Zitat von QuickAndDirty (Beitrag 1105093)
Folgende "Fehlerquellen" sind bekannt:
-Prozess vom User System kann/soll mann nicht terminieren. (Ist ok, deswegen laufen alle Prozesse als Administrator)
-Prozess von einem anderen User kann/soll man nicht terminieren. (Ist ok, alle laufen im User Kontext Administrator)

Das ist noch nicht zwingend ok, der Administrator ist ja auch nicht von Haus aus allmächtig, sei es wegen UAC ab Vista oder wegen fehlender Privileges. Selbst ein Service, der als LocalSystem läuft und mehr darf als ein Admin, darf ohne weiteres auch noch nicht alles.

Frage 1: um welches OS handelt es sich?

Frage 2: Hat der Guard evtl. noch kein SeDebugPrivilege? Aber der Service läuft ja vermutlich als LocalSystem und ist somit noch "über" dem Admin. Also: SeDebugPrivilege nicht planlos verwenden, aber schauen ob es notwendig sein könnte.

Weiter mit noch was einfacherem... aus der Doku:
Zitat:

The handle must have the PROCESS_TERMINATE access right.
Frage 3: Prüfst Du, ober der Handle, den Du TerminateProcess übergibst, überhaupt korrekt erhalten wurde? Oder schlägt der fehl, loggst Du dann GetLastError? Ich weiß, eigentlich eine dumme Frage, aber Du glaubst nicht wie oft hier an der Fehlerbehandlung geschludert wird...

QuickAndDirty 10. Jun 2011 09:38

AW: TerminateProcess geht nicht die Zweite
 
Zitat:

Zitat von CCRDude (Beitrag 1105596)
Zitat:

Zitat von QuickAndDirty (Beitrag 1105093)
Folgende "Fehlerquellen" sind bekannt:
-Prozess vom User System kann/soll mann nicht terminieren. (Ist ok, deswegen laufen alle Prozesse als Administrator)
-Prozess von einem anderen User kann/soll man nicht terminieren. (Ist ok, alle laufen im User Kontext Administrator)

Das ist noch nicht zwingend ok, der Administrator ist ja auch nicht von Haus aus allmächtig, sei es wegen UAC ab Vista oder wegen fehlender Privileges. Selbst ein Service, der als LocalSystem läuft und mehr darf als ein Admin, darf ohne weiteres auch noch nicht alles.

Beide laufen mit den rechten des Domänen Administrators...sollte der Guard besser als Lokalessystem angemeldet sein?

Zitat:

Zitat von CCRDude (Beitrag 1105596)
Frage 1: um welches OS handelt es sich?

Entweder 2008 oder Windows 7
Keine Ahnung welches Servicespack oder Build.
Aber es poppt keine UAC auf wenn man was macht.

Zitat:

Zitat von CCRDude (Beitrag 1105596)
Frage 2: Hat der Guard evtl. noch kein SeDebugPrivilege? Aber der Service läuft ja vermutlich als LocalSystem und ist somit noch "über" dem Admin. Also: SeDebugPrivilege nicht planlos verwenden, aber schauen ob es notwendig sein könnte.

Ich weiß nicht mal was das SeDebugPrivilge ist...
Und auch im einrichten von Gruppenrichlinien oder verwalten von Active-Directories habe ich keine Ahnung....aber soweit ich weiß sind das zwei Stichwörter die erfunden wurden um die Kreativität der Entwickler zu behindern.

Ich sollte den Guard wirklich mal als LocalesSystem anmelden, hmm?

Zitat:

Zitat von CCRDude (Beitrag 1105596)
Weiter mit noch was einfacherem... aus der Doku:
Zitat:

The handle must have the PROCESS_TERMINATE access right.
Frage 3: Prüfst Du, ober der Handle, den Du TerminateProcess übergibst, überhaupt korrekt erhalten wurde? Oder schlägt der fehl, loggst Du dann GetLastError? Ich weiß, eigentlich eine dumme Frage, aber Du glaubst nicht wie oft hier an der Fehlerbehandlung geschludert wird...

[/QUOTE]
Oh je....
Der Guard wurde von einem Kollegen geschrieben und ich schaue mal ob da irgendwo getlasterror aufgerufen wird....aber ich bezweifle es (weil der produziert auch so Code zeilen wie
Code:
If not(b<>False) Then
diese)

Das überwachte Programm ist von mir...und der eigentliche Fehler ist ja auch das es sich aufhängt und erst notwendig macht das der Guard es abschießen/neustarten möchte.
Ich kämpfe hier also ein 2 Fronten...beim Kunden versuche ich zu ermitteln warum es abstürzt und das reicht dem Kollegen um selbst in sachen Guard NICHT tätig zu werden...deswegen bin ich es hier der diesen Thread auf gemacht hat
(ja unsere Firma ist ein Kindergarten).

mkinzler 10. Jun 2011 09:39

AW: TerminateProcess geht nicht die Zweite
 
Delphi-Quellcode:
If not(b<>False) Then
ist ja echt abenteuerlich

CCRDude 10. Jun 2011 11:07

AW: TerminateProcess geht nicht die Zweite
 
Als "LocalSystem" (nicht "LokalesSystem") kannst Du Dich nicht einfach so anmelden; Systemdienste etwa arbeiten unter diesem Account, manchmal auch LocalService, NetworkService sowie einige andere. Wenn Du im Windows Task Manager Dir die Prozesse aller User anzeigen lässt, wirst Du die (unter leicht anderem Namen) sehen. Das halt also nichts mit der Domäne zu tun.

Privileges betreffen Rechte, die sich ein Programm teilweise erst noch anfordern muss. Siehe auch MSDN: How to Use the SeDebugPrivilege - da wird sogar die OpenProcess/TerminateProcess-Thematik erwähnt.

Und nein, Privileges und auch Gruppenrichtlinien wurden nicht erfunden, um Programmierer zu ärgern, sondern in diesem Kontext auch, um Sicherheit zu schaffen - was zugegeben Programmierer manchmal zwingt, sich Gedanken über Sicherheit zu machen, was ich allerdings nicht als Ärgern einstufen würde ;)

Ich glaube aber ehrlich gesagt, der Kindergarten ist die größere Baustelle :D Eigentlich würde ich ja empfehlen, euch ein bisschen in Tokens und Privileges einzulesen, aber ich glaube da täte erstmal ein Kommunikations und ggfls. Führungsseminar not, wenn jemand in einer kundenkritischen Situation einfach so Fehler in seinem Programm ignorieren darf ;)

QuickAndDirty 24. Jun 2011 12:41

AW: TerminateProcess geht nicht die Zweite
 
Gelöst ---
Ursache Eine Quelloffene Treiber-DLL im System-Verzeichis wurde genutzt um per IP einen Hardware in der Virtuellen Maschine des Kunden verfügbar zu machen.

Wann immer der IP Server mit dem die DLL sich verband, aus welchen gründen auch immer, nicht rechtzeitig antwortete, meldete sie es mit "::MessageBox" aufrufen....

Leider kann man wohl ein Programm nicht abschießen wenn es in einer System DLL hängt und im dienst ist die MessageBox ja nicht sichtbar.


1.
Mal ne frage aus Neugierde: Dürfen System DLLs überhaupt Messageboxen aufmachen? Weil das ist ja mit hinblick auf einen gebrauch in einem Dienst ziemlich suboptimal.

2.
Kann ich von außen herausfinden ob ein Dienst gerade in einer Messagebox hängt und diese "drücken".


Wir haben es jetzt so geregelt das wir besagter mini dienst die Hardware selbst direkt benutzt....
und jetzt seit einigen Tagen keine Probleme mehr ^^

CCRDude 24. Jun 2011 15:43

AW: TerminateProcess geht nicht die Zweite
 
1. Hängt sicherlich etwas damit zusammen, was Du unter Treiber-DLL bzw. System-DLL meinst. Ist es ein richtiger Treiber, sicherlich nicht. Meinst Du aber nur die Funktionalität - kann ja sein, daß die auch in einer normalen Anwendung eingebunden werden kann/soll. Dann ist es nur noch schlechter Stil ;) Zudem lassen sich System Services per Flag auf "interaktiv" setzen. In älteren Windows-Versionen (Windows 2000?) war dieses Flag evtl. nicht notwendig, später kam es aus Absicherungsgründen hinzu (Prozesse mit Systemrechten sollten nicht direkt über das UI mit dem Benutzer kommunizieren).

2. "Einfacher" wäre es vermutlich, die MessageBox-Funktion innerhalb des Prozesses zu hooken und so einfach zu ignorieren (oder, um's ganz fein zu machen, ins Eventlog umzuleiten). Dazu gibt's hier in der DP glaub ich auch Beispiele :)

QuickAndDirty 24. Jun 2011 23:26

AW: TerminateProcess geht nicht die Zweite
 
Ok, auch wenn es Offtopic in bezug auf den Threadtitel ist...es ist ja noch der selbe Fall...

Zitat:

Zitat von CCRDude (Beitrag 1108150)
1. Hängt sicherlich etwas damit zusammen, was Du unter Treiber-DLL bzw. System-DLL meinst.
Ist es ein richtiger Treiber, sicherlich nicht.

Ich meine ein Datei in C:\Windows\System32 es ist kein Treiber nur eine DLL die systemweit und von jeder X beliebigen Anwendung - oder auch Dienst - benutzt werden können sollte. Ist eben eine Capi2032.dll von Shamrock und dazu gibt es irgendwie zwischen 16Kb und 32Kb Opensource C++ Code... ich verwende die ja auch...aber ich muss mich nicht auf das dauerhafte Funktionieren dieser Geschichte verlassen...

CAPI ist für schon so die Schnittstelle zur ISDN-Karte...sollte eigentlich(wenn es verkauft werden würde und nicht umsonnst Opensourcezeug ist) mit der selben Sorgfallt und Misstrauen gegenüber den Randbedingungen programmiert sein wie ein Treiber.

Zitat:

Zitat von CCRDude (Beitrag 1108150)
Meinst Du aber nur die Funktionalität - kann ja sein, daß die auch in einer normalen Anwendung eingebunden werden kann/soll. Dann ist es nur noch schlechter Stil ;) Zudem lassen sich System Services per Flag auf "interaktiv" setzen. In älteren Windows-Versionen (Windows 2000?) war dieses Flag evtl. nicht notwendig, später kam es aus Absicherungsgründen hinzu (Prozesse mit Systemrechten sollten nicht direkt über das UI mit dem Benutzer kommunizieren).

Das wäre leider keine lösung...aber da es Opensource ist...vielleicht werde ich mal in nem C++ board betteln das jemand mir den code ohne "::MessageBox" kompiliert...habe hier keine IDE dafür und betteln ist schneller als mich mit ner gnu C++ und Eclipse oder MS C++ und VS ... rumzuschlagen.
Es ist jetzt nicht WIRKLICH entscheidend, aber es wäre sicher von Vorteil für so manchen wenn es das Projekt so gäbe das es auch in Diensten funktioniert....
(Ich bereite morgen mal nen freundlich Text vor und Kommentiere die MessageBoxen aus)

Zitat:

Zitat von CCRDude (Beitrag 1108150)
2. "Einfacher" wäre es vermutlich, die MessageBox-Funktion innerhalb des Prozesses zu hooken und so einfach zu ignorieren (oder, um's ganz fein zu machen, ins Eventlog umzuleiten). Dazu gibt's hier in der DP glaub ich auch Beispiele :)

Vermutlich nicht "Einfacher", aber da ich ja im Prinzip immer damit rechnen muss das irgendwelche von meinen Diensten genutzten Treiber oder Bibliotheken oder sonnst etwas eine MessageBox werfen kann, würde es wohl der Stabilität des Produktes entgegenkommen, wenn ich den von dir vorgeschlagenen Weg einschlage.

Muss also was über Hooks lernen :( *nicht will*

CCRDude 25. Jun 2011 14:17

AW: TerminateProcess geht nicht die Zweite
 
Da es nur Hooks innerhalb Deiner Anweisung und nicht systemweit sein müssen, hält sich der Streß in Grenzen, denke ich :)

Schaue Dir mal die executehook.zip hier an. Davon brauchst Du quasi nur die HookUnit.pas, bzw. sogar nur einzelne Funktionen daraus (nämlich FinalFunctionAddress und PatchAddress).

Grob gesagt, machst Du ein:
Code:
type
   TMessageBoxA = function(hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): Integer; stdcall;
   TMessageBoxW = function(hWnd: HWND; lpText, lpCaption: PWideChar; uType: UINT): Integer; stdcall;

var
   OldMessageBox: TOldMessageBoxA; // unter DXE: *W
   OldMessageBoxA: TOldMessageBoxA;
   OldMessageBoxW: TOldMessageBoxW;

...

procedure NewMessageBoxA(hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): Integer; stdcall;
begin
   // log message to some kind of log instead.
   // to display message box, call OldMessageBoxA here.
end;
procedure NewMessageBoxW(hWnd: HWND; lpText, lpCaption: PWideChar; uType: UINT): Integer; stdcall;
begin
   // log message to some kind of log instead.
   // to display message box, call OldMessageBoxA here.
end;

...

initialization
   @OldMessageBox := FinalFunctionAddress(MessageBox);
   @OldMessageBoxA := FinalFunctionAddress(MessageBoxA);
   @OldMessageBoxW := FinalFunctionAddress(MessageBoxW);
   PatchAddress(@OldMessageBox, @NewMessageBox);
   PatchAddress(@OldMessageBoxA, @NewMessageBoxA);
   PatchAddress(@OldMessageBoxW, @NewMessageBoxW);
finalization
   PatchAddress(@NewMessageBox, @OldMessageBox);
   PatchAddress(@NewMessageBoxA, @OldMessageBoxA);
   PatchAddress(@NewMessageBoxW, @OldMessageBoxW);
end;
Das ist jetzt kein getesteter Code, sondern nur per copy'n'paste an Deine Situation angepasst, damit Du das Schema versteht. Ich arbeite inzwischen mit madCodeHook, kann mich daher nur noch grob erinnern, wie diese Methode ging.

QuickAndDirty 25. Jun 2011 22:17

AW: TerminateProcess geht nicht die Zweite
 
cool danke .....Dude!


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:33 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