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 Schließen eines fremden Programms verhindern (https://www.delphipraxis.net/40327-schliessen-eines-fremden-programms-verhindern.html)

TStringlist 14. Feb 2005 13:02


Schließen eines fremden Programms verhindern
 
Hallo,

wie schon in der Überschrift angedeutet, möchte ich in meinem Programm verhindern, dass ein anderes fremdes Programm beendet werden kann. Ein Hooken dieses anderen fremden Progs wäre dabei kein Problem. Leider aber scheint ein solches Prog-Beenden (z.B. per X-Button in der Title-Leiste) dort nicht über ein WM_Close abgewickelt zu werden...

Gibt's da vielleicht sonst noch Messages (o. ggf. auch andere Techniken) mittels denen man das bewerkstelligen kann?

Thx im Voraus.

TopDogg 14. Feb 2005 13:10

Re: Schließen eines fremden Programms verhindern
 
Spontan fehlt mir nur WM_DESTROY ein.

alcaeus 14. Feb 2005 13:19

Re: Schließen eines fremden Programms verhindern
 
Hallo TStringList,

ganz wirst du das nie verhindern können, denn wenn man ein Programm über den Taskmanager abschießt, wird deine Anwendung auch nichts dagegen sagen können. Du kannst höchstens einen "Watchdog" machen, welcher die Anwendung sofort wieder startet sobald sie beendet wurde. Inwieweit das immer möglich ist, bleibt fraglich, denn der Effekt ist nicht der gleiche wie beim Schließen verhindern.

Greetz
alcaeus

TStringlist 14. Feb 2005 13:30

Re: Schließen eines fremden Programms verhindern
 
Thx all.


@TopDogg

WM_Destroy scheint diesbezüglich leider auch nicht ans Prog abgeschickt zu werden.

Wie ich eben feststelle, WM_Quit allerdings schon ...nur klappt's dabei leider irgendwie nicht mit dem Abfangen (... wenn das dann überhaupt die Lösung wäre).

Abzufangen versuche ich das im Message-Hook so:

Delphi-Quellcode:
if PMsg(lp)^.message = WM_Quit then begin
  windows.beep(300,25);
  Result := 0;
  exit;
end;
das gänge doch so, oder?


@alcaeus

So ein Watchdog habe ich tatsächlich schon, nur dachte ich jetzt, es einfach gleich ganz zu verhindern, wäre irgendwie doch noch etwas eleganter. ...Das Verhindern des schließens des Progs über den Taskmanager wäre dabei auch nicht so wichtig. Es soll eher nur verhindert werden, dass das fremde Programm aus Versehen geschlossen wird.

Boombuler 14. Feb 2005 14:03

Re: Schließen eines fremden Programms verhindern
 
Lasst mich lügen aber ich glaub zu diversen Closehooks gibts hier schon themen genug....

Greetz
Boombuler

TStringlist 14. Feb 2005 14:24

Re: Schließen eines fremden Programms verhindern
 
Allgemein zu Hooks schon, aber nicht zu quasi Closehooks. Ansonsten, stell doch mal bitte 2 o. 3 Links davon hier rein. Danke :lol:

Boombuler 14. Feb 2005 16:18

Re: Schließen eines fremden Programms verhindern
 
Sorry war kein Hook...
aber ich denke mit abfangen folgender Message solltest du erfolg haben:
Delphi-Quellcode:
SendMessage(Handle, WM_SYSCOMMAND, SC_CLOSE, 0);
ich hab auch mal n CloseHook geschrieben hab allerdings den QT verlegt! Ich meine aber ich hab eben jene Message abgehookt!

Greetz
Boombuler

[edit]
hab das dingen gerad wieder gefunden!

Delphi-Quellcode:
type
  PTMsg = ^TMsg;

function CloseHookProc(nCode: Integer; wParam: WPARAM; lParam:Integer):
 LRESULT; stdcall;
var aCopy:TCopyDataStruct;
begin
  case nCode < 0 of
    FALSE:
      begin
       if (PTMsg(lparam).message = WM_Close) then
        begin
           //Hier springt der rein wenn ein programm geschlossen wurde
        end;
      end;
  end;
Result := CallNextHookEx(HookHandle, nCode, wParam, lParam);
end;

TStringlist 14. Feb 2005 17:23

Re: Schließen eines fremden Programms verhindern
 
doch, ja, WM_SysCommand sähe eigentlich ganz gut aus. Habe auch gerade diesbezüglich in der PSDK gelesen, dass diese Message bei einem solchen Ereignis (also einem App-Closen über die X-Button rechts in der Title-Leiste) dann eigentlich auch abgeschickt wird. Aber leider kommt sie in der HookProc irgendwie nicht an (egal mit welchem weiteren wParam-Wert).

Zur allgemeinen Information vielleicht noch: Das gehookte Prog ist hier nur der ganz normale Rechner, wohl immer zu finden per FindWindow mit den Parametern ('Rechner','SciCalc').

Und hier nochmal kurz, welche Messages beim App-Closen in der HookProc auch leider nur vorbeikommen. (WM_LButtonDown habe ich nur zum generellen Test der HookProc mit dazugenommen):

Delphi-Quellcode:
function PROC(nCode: Integer; wp: wParam; lp: lParam): LongInt; stdcall;
var pt : TSmallPoint;
begin
  if (nCode >= HC_ACTION) then
    case PMsg(lp)^.message of
      WM_Close : Beep; <-- gibt's nie
      WM_Destroy : Beep; <-- gibt's nie
      WM_Quit : begin
                  windows.Beep(300,25); <-- kommt, ist aber leider nicht abzufangen...
                  // PMsg(lp)^.message := WM_Null // ...wenigstens so nicht
                  // Result := 0;
                  // exit;
                end;
      WM_SysCommand : windows.beep(1000,25); <-- gibt's nie
      WM_LButtonDown : windows.beep(2500,25); <-- kommt bei jedem LButtonDown
    end; { of case }

  Result := CallNextHookEx(buf^.hMSNHook, nCode, wp, lp);
end;

TStringlist 14. Feb 2005 17:43

Re: Schließen eines fremden Programms verhindern
 
Ich glaube einen Lösungs-Ansatz gefunden zu haben.

Wie ich gerade feststellte, geht es nämlich diese besagte X-Button in der Title-Leiste durch ein Abfangen der WM_NCLButtonDown-Message zu blockieren. Alles was ich also jetzt noch zu tun habe, ist, die absolute X/Y-Position des Rechners zu bestimmen, die relative Position der besagten X-Button darauf und ob die Mouse-Position sich dann gerade darüber befindet. In dem Fall schlucke ich diese Message einfach (was ja funktioniert) und die Sache ist geritzt...

Thx all nochmal...


[edit] ...und das Closen der Fremd-App über das Menue welches über die rechte Maustaste aus der App-Button in der Task-Bar aufpopt, das ist dann tatsächlich über das abfangen der WM_SysCommand-Message blockierbar.

TStringlist 14. Feb 2005 21:18

Re: Schließen eines fremden Programms verhindern
 
und abschließend auch nochmal die ganz nette Lösung:

Delphi-Quellcode:
library HookDll;

uses
  Windows,
  Messages,
  SysUtils;

const
  WM_SpecialEvent = WM_User + 1678;

type
 THookRec = record
   hOldHook: HHOOK;
   hOwnProg: HWND;
   hZielApp: HWND;
 end;

var
 hMap: DWord;
 buf: ^THookRec;


function GetMsgProc(nCode: Integer; wp: wParam; lp: lParam): LResult; stdcall;

procedure KillMsgAndPostInfo;
const Closing = 1234;
      blocked = 5678;
begin
  PMsg(lp)^.message := WM_Null;
  // plus einem Info-Post an den Hook-Erzeuger
  PostMessage(buf^.hOwnProg, WM_SpecialEvent, Closing, blocked);
end;

var ARect : TRect;
begin
  if (nCode >= HC_ACTION) then
    case PMsg(lp)^.message of
      WM_Close :        // beim Closen übers Main-Menue
                         KillMsgAndPostInfo;
      WM_SysCommand :   // beim Closen übers Window-Menue
                         if PMsg(lp)^.wParam = SC_CLOSE then
                           KillMsgAndPostInfo;
      WM_NCLButtonDown : begin // beim Closen über die X-Button in der Title-Bar
                           GetWindowRect(buf^.hZielApp,ARect);
                           ARect.Right := ARect.Right -4;
                           ARect.Left := ARect.Right -18;
                           ARect.Top := ARect.Top +3;
                           ARect.Bottom := ARect.Top +19;

                           with PMsg(lp)^.pt, ARect do
                           if (X >= Left) and (X <= Right)
                           and (Y >= Top) and (Y <= Bottom) then
                             KillMsgAndPostInfo;
                         end;
    end; { of case }

  Result := CallNextHookEx(buf^.hOldHook, nCode, wp, lp);
end;

.
.
edit: Nachträglicher Einbau des Abfangens auch noch einer WM_Close-Message.

...was z.B. dann nötig ist (nicht aber bei calc.exe), wenn man diesen Hook auch auf Applications anwenden möchte, welche auch zusätzlich noch eine Programmbeende-Möglichkeit übers Mainmenue besitzten (Mainmenue --> Datei --> Beenden).

edit: nur noch Mini-Kosmetik

Boombuler 15. Feb 2005 07:39

Re: Schließen eines fremden Programms verhindern
 
Ich hätte auch nicht die Message verändert sondern einfach Result := 0 beim Abbrechen. (Toll nu fehlt mir das Verb!)
So kannst du die HookChain unterbrechen und der Calc bekommt gar keine Msg mehr!

Greetz
Boombuler

TStringlist 15. Feb 2005 09:12

Re: Schließen eines fremden Programms verhindern
 
nee, nur alleine mit einem "Result:=0" (plus jeweils einem exit dahinter ..dann in der Case-Anweisung) geht's nicht. Man könnte es höchstens noch zusätzlich machen, ungefähr so wie ich das ja auch "Gestern um 18:23" beim beabsichtigten WM_Quit-Abfangen versuchte.

PMM 17. Feb 2005 11:03

Re: Schließen eines fremden Programms verhindern
 
Hallo TStringlist,
ich hab mal versucht das nachzuvollziehen, bekomme es aber nicht hin. Bei mir wird nur das X der Titelzeile blockiert (auch das nicht ganz zuverlässig). Welchen WH_xxx Typ verwendest du bei SetWindowsHookEx?
PMM

TStringlist 17. Feb 2005 12:29

Re: Schließen eines fremden Programms verhindern
 
Hi PMM, gemäß des PSDKs ist "GetMsgProc" die offizielle Placeholderbezeichnung für die Application-defined HookProc eines WH_GETMESSAGE-Hooks.

edit: ...außerdem, wegen der nicht ganz zuverlässig blockierbaren X-Button nehme ich an, wirst du dann als OS das Windows-XP benutzen (da sind diese Tasten wohl etwas anders dimensioniert als beim W2k). In diesem Falle müsstest du diese Korrekturwerte nämlich entsprechend anpassen ...jene welche mit denen ich vom ProgRect auf das X-Button-Rect zurückrechne. Das Beste wäre allerdings diese Korrekturwerte für beide OS zu wissen und die dann, je nachdem auf welchem OS das Prog gerade läuft, dann auch noch zusätzlich über die Parameterliste der SetHook-Funktion zur eigentlichen HookProc mit durchzuschleusen.

PMM 17. Feb 2005 15:14

Re: Schließen eines fremden Programms verhindern
 
Txs TStringList,
WH_GETMESSAGE hatte ich geahnt und funktioniert auch für WM_NCLButtonDown, die Korrekturen für WIN2K werde ich schon rausfinden (andere brauch ich hier nicht :-)
Das Problem ist, dass weder WM_CLOSE noch WM_SysCommand jemals erreicht werden :-(
PMM

TStringlist 17. Feb 2005 17:06

Re: Schließen eines fremden Programms verhindern
 
Ein nicht ganz korrekt berechnetes X-Button-Rect könnte übrigens auch darauf zurück gehen, dass das Programm (bei dem du das Schließen so verhindern willst) mit BorderStyle=bsNone erzeugt wurde. Denn dann wären eventuelle BorderIcons (also auch die X-Button) natürlich Individual-Anfertigungen und diese Korrektur-Werte zur Errechnung des X-Button-Rect müssten demzufolge auch immer entsprechend extra angepasst werden. Die im obigen Beispiel diesbezüglich benutzen Werte passen jedenfalls für BorderStyle=bsNormal-Programme und solche von der Sorte Notepads etc..

Und da wir gerade bei Notepad sind... Wenn ich das z.B. übers MainMenue (Datei -> Beenden) beenden möchte, dann ist jedenfalls auch ein Abfangen einer WM_Close-Message nötig. Welche Message da aber letztlich immer abgefangen werden muss, hängt dann aber wohl auch vom Programm selbst ab. Je nach dem, wie es den Programmabbruch eben für sich selbst verursacht. So muss z.B. bei einem Delphi-Prog, das über die close-Methode beendet wird, kein WM_Close abgefangen werden, sondern wider Erwarten ein WM_Quit.

Warum bei dir keine WM_SysCommand-Message (mit wParam = SC_CLOSE) in der HookProc vorbeikommt kann ich mir allerdings nicht so recht erklären. Die müsste beim Prog-Abbruch übers WindowMenue (also dasjenige, welches beim Rechtsclick auf die Programm-Button in der Taskbar aufpopt !) da eigentlich schon auftauchen.

dizzy 17. Feb 2005 17:27

Re: Schließen eines fremden Programms verhindern
 
Bei einer Form mit bsNone entfällt der Non-Client-Bereich, weshalb es nie zu einer WM_NCL* Message kommen wird ;). (Zumindest dann nicht, wenn es nicht explizit reimplementiert wurde... wenn das überhaupt geht.)

Dass heisst dass ein solcher Fake-X-Button sehr wahrscheinlich (aber auch nur wahrscheinlich) ein WM_Close auslösen wird. Damit entfällt ein mühsähliges Anpassen des Kollisionsbereiches ;).

\\edit: Mit XP-Styles hat man mit deiner Methode im Übrigen ganz verloren, da der Button dort völlig beliebig im NC-Bereich verteilt werden kann. Du müsstest JEDES existierende Style kennen und separat implementieren. So sehr allgemein ist dein Ansatz daher leider nicht - wobei ich aber zugeben muss, dass ich mangels Erfahrung in diesem Bereich, keinen besseren Lösungsvorschlag anbieten kann 8).

TStringlist 17. Feb 2005 18:25

Re: Schließen eines fremden Programms verhindern
 
Zitat:

Zitat von dizzy
Bei einer Form mit bsNone entfällt der Non-Client-Bereich, weshalb es nie zu einer WM_NCL* Message kommen wird ;).

jo, lustig aber wahr,...

...da hat mich wohl einfach nur der missionarische Eifer etwas zu sehr gepackt und irgendwohin davongetragen :mrgreen: ...

Übrigens ist es wahr, bei Delphi-Progs, die über die close-Methode abbrechen (wie wahrscheinlich immer bei dann Fake-X-Buttons), ist ein WM_Quit abzufangen.

Außerdem sollte die Lösung ja auch sowieso nur eine sein, mittels der ein spezielles, schon bekanntes anderes Programm entsprechend präpariert werden kann. Und für irgendein solches, eben schon existierendes, anderes Programm ist es nach einer kleinen Anpassung immer noch eine brauchbare Methode, imo. Programme die sowas über einen globalen Hook bei gleich allen anderen (sonst eher unbekannten) Progs verursachen würden, gehörten dann ja wahrscheinlich auch ohnehin mehr in die Spalte "Scherzartikel".


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:08 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz