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 Ruhezustand blockieren-> Versuch erkennen -> selbst auslösen (https://www.delphipraxis.net/65032-ruhezustand-blockieren-versuch-erkennen-selbst-ausloesen.html)

ichbins 11. Mär 2006 11:14


Ruhezustand blockieren-> Versuch erkennen -> selbst au
 
Hi, wie geht das?

ich habe ein Programm das "vertrauliche Daten" anzeigen kann, und wenn der User jetzt den Ruhezustand auslöst, will ich das blockieren, alle Daten speichern + beenden und dann selbst den Ruhezustand auslösen, so dass nicht beim nächsten Start die Daten wieder angezeigt werden.

nen Code für Ruhezustand auslösen hab ich irgendwo hier schon mal gefunden, das ist kein Problem.

aber wie kann ich ihn blockieren und sogar einen Versuch erkennen?

[ich hoffe mal ich hab in die richtige Sparte gepostet]

DevilsCamp 10. Apr 2006 07:33

Re: Ruhezustand blockieren-> Versuch erkennen -> selbs
 
MSDN-Library durchsuchenWM_POWERBROADCAST ist dein Freund.

Damit brauchst du den Ruhezustand nicht blockieren, sondern einfach nur auf die Message reagieren und deine Daten "verstecken" sobald diese Nachricht kommt.

Union 10. Apr 2006 08:07

Re: Ruhezustand blockieren-> Versuch erkennen -> selbs
 
Hi ichbins,

im Interface:
Delphi-Quellcode:
procedure WMPowerBroadcast(var Msg : TWMPower) ; message WM_POWERBROADCAST;
In der Implementation:
Delphi-Quellcode:
//------------------------------------------------------------------------
procedure TfrmMain.WMPowerBroadcast(var Msg: TWMPower);
//------------------------------------------------------------------------
// Suspend ablehnen
//------------------------------------------------------------------------
begin
   Msg.Result := BROADCAST_QUERY_DENY;
end;

DevilsCamp 10. Apr 2006 08:15

Re: Ruhezustand blockieren-> Versuch erkennen -> selbs
 
Wie ich schon geschrieben habe:
Wenn er soweit ist, dann braucht er den Versuch doch nicht blockieren um ihn dann selber zu starten.

Problem dabei ist nämlich:
Er blockiert den Versuch in den Ruhezustand zu gehen, "versteckt" seine Daten und initiiert den Ruhezustand dann selber.
Folge: Er landet WIEDER in seiner Behandlungsroutine wo er den Ruhezustand blockiert und wieder aufruft => Endlosscheife.

Aber wenn er schon soweit ist den Versuch in den Ruhezustand zu gehen zu überprüfen, dann kann er doch dort gleich seine Daten "verstecken" und den Ruhezustand zulassen.

Union 10. Apr 2006 08:20

Re: Ruhezustand blockieren-> Versuch erkennen -> selbs
 
Das geht nicht, da das Suspend sehr zeitkritisch ist. Wenn man die Broadcast Nachricht nicht sofort beantwortet, wird das Suspend ausgelöst, ohne dass man darüber die Kontrolle hat. Besser wäre es, die Nachricht dann zu blockieren, die "Daten zu verstecken" und ein entsprechendes Flag zu setzen. Dann die Nachricht an sich selber schicken. Da das Flag jetzt gesetzt sein sollte, wird auf die Nachricht nicht mehr reagiert.

DevilsCamp 10. Apr 2006 08:26

Re: Ruhezustand blockieren-> Versuch erkennen -> selbs
 
Zitat:

Zitat von Union
Das geht nicht, da das Suspend sehr zeitkritisch ist. Wenn man die Broadcast Nachricht nicht sofort beantwortet, wird das Suspend ausgelöst, ohne dass man darüber die Kontrolle hat.

Wo bitte hast du das her? Laut MSDN erwartet Windows von JEDEM Programm eine Antwort. Standardmäßig dürfte ein Delphi Programm TRUE zurückliefern, da er aber auf die Nachricht reagiert, sollte Windows solange warten, bis eine Antwort zurückkommt.



<edit>
OK, hast recht. Aber er hat immerhin ZWANZIG Sekunden Zeit auf die Nachricht zu reagieren. Das osllte wohl ausreichen.
</edit>

Union 10. Apr 2006 08:31

Re: Ruhezustand blockieren-> Versuch erkennen -> selbs
 
Das ist praktische Erfahrung. Und Windows wartet auch nicht auf jedes Programm. Sonst würde ja das Runterfahren verhindert durch Programme, die diese Message gar nicht verarbeiten.

DevilsCamp 10. Apr 2006 08:33

Re: Ruhezustand blockieren-> Versuch erkennen -> selbs
 
Siehe mein Edit.

Das Programm hat 20 Sekunden Zeit auf PBT_APMQUERYSUSPEND zu reagieren und ebenfalls 20 Sekunden bei PBT_APMSUSPEND.

Das sollte wirklich reichen. Denn ich denke mal es geht auch deutlich schneller, wenn er das Programm beendet.

Union 10. Apr 2006 08:37

Re: Ruhezustand blockieren-> Versuch erkennen -> selbs
 
Wo hast Du denn die 20 Sekunden her? Das ist vielleicht der Fall bei einem Shutdown, aber was ist bei Hibernation? Dort bleiben zwar die Daten erhalten (theroetisch), aber wenn man dem nicht traut oder man gerne noch eine offene SQL-Server-Verbindung schliessen möchte... Und gerade auf Laptops macht das dann whuusch und weg.

DevilsCamp 10. Apr 2006 08:39

Re: Ruhezustand blockieren-> Versuch erkennen -> selbs
 
Zitat:

Zitat von Union
Wo hast Du denn die 20 Sekunden her?

MSDN-Library durchsuchenPBT_APMQUERYSUSPEND und MSDN-Library durchsuchenPBT_APMSUSPEND

Jeweils der erste Link

Union 10. Apr 2006 08:45

Re: Ruhezustand blockieren-> Versuch erkennen -> selbs
 
Da steht aber:
Zitat:

Zitat von msdn
An application should process this event as quickly as possible

und
Zitat:

Zitat von msdn
The system allows approximately 20 seconds

Das ist für mich keine genaue Aussage. Zudem gibt es einen Registry-Eintrag, mit dem man die Wartezeit reduzieren bzw. sogar auf Null setzen kann.

DevilsCamp 10. Apr 2006 08:56

Re: Ruhezustand blockieren-> Versuch erkennen -> selbs
 
Zitat:

Zitat von Union
Da steht aber:
Zitat:

Zitat von msdn
An application should process this event as quickly as possible

und
Zitat:

Zitat von msdn
The system allows approximately 20 seconds

Das ist für mich keine genaue Aussage. Zudem gibt es einen Registry-Eintrag, mit dem man die Wartezeit reduzieren bzw. sogar auf Null setzen kann.

Auf NULL? Da kann ja noch nichtmal ein Treiber reagieren.

Und anscheinend ist für Microsoft "As quickly as possible" = "The system allows approximately 20 seconds"
Und das "verstecken" der Daten sollte allerdings sicher nicht mehr als eine, max. zwei Sekunden dauern.

Ich kann aus meiner Erfahrung jedenfalls sagen, dass die Zeit ausreicht noch Daten an einen Server zu schicken und auf Antwort zu warten.


Aber das sollte ichbins selber entscheiden wie er es machen will.

hitzi 10. Apr 2006 08:57

Re: Ruhezustand blockieren-> Versuch erkennen -> selbs
 
Zitat:

Zitat von Union
Zudem gibt es einen Registry-Eintrag, mit dem man die Wartezeit reduzieren bzw. sogar auf Null setzen kann.

Wo ist das Problem - dann muss eben das Programm den Registry-Eintrag checken und bei Bedarf anpassen - allerdings nach Programmbeendigung auch wieder auf den Ursprungseintrag zurücksetzen, damit's keinen Ärger mit dem User gibt.

TeronG 10. Apr 2006 09:32

Re: Ruhezustand blockieren-> Versuch erkennen -> selbs
 
Zitat:

Zitat von hitzi
Wo ist das Problem - dann muss eben das Programm den Registry-Eintrag checken und bei Bedarf anpassen - allerdings nach Programmbeendigung auch wieder auf den Ursprungseintrag zurücksetzen, damit's keinen Ärger mit dem User gibt.

:shock: Du willst doch nicht etwa ungefragt in der Registry rumspielen :?:

Zitat:

Zitat von DevilsCamp
... Er landet WIEDER in seiner Behandlungsroutine wo er den Ruhezustand blockiert und wieder aufruft => Endlosscheife. ...

Sowas könnte mal mit ner einfachen Boolean verhindern ... :gruebel:

hitzi 10. Apr 2006 10:54

Re: Ruhezustand blockieren-> Versuch erkennen -> selbs
 
Zitat:

Zitat von TeronG
Du willst doch nicht etwa ungefragt in der Registry rumspielen

Warum nicht? Wenn es wirklich so sicherheitsrelevant ist, ob das Programm geöffnet bleibt oder nicht, dann kann man auch mal die Registry "missbrauchen". Man kann ja bei der ersten Benutzung oder bei der Installation des Programmes auf die Änderung und die Gründe hinweisen. Außerdem ist die Änderung doch nur aktiv, wenn das Programm gestartet ist.

Was machen denn die ganzen "Internet-Cafe Programme", die alle möglichen Sachen vor dem User über die Registry verstecken. Wenn es die Sicherheit erfordert, sollte man schon auch zu solchen Mitteln greifen dürfen.

Gruss

TeronG 10. Apr 2006 12:51

Re: Ruhezustand blockieren-> Versuch erkennen -> selbs
 
Zitat:

Zitat von hitzi
Warum nicht?

Zitat:

Zitat von hitzi
Man kann ja bei der ersten Benutzung oder bei der Installation des Programmes auf die Änderung und die Gründe hinweisen.

eben ... soo einfach und schon weis der User bescheid ...
Zitat:

Zitat von hitzi
Außerdem ist die Änderung doch nur aktiv, wenn das Programm gestartet ist.

und wenn während des betriebes des Programmes der wert geändert wird? (regedit oder andere software ..)
Zitat:

Zitat von hitzi
Was machen denn die ganzen "... Programme", die alle möglichen Sachen ....

Das mag jeder sehen wie er will (das wird eh jeder so machen ^^) aber ich find es einfach nich gut. Und nur weil es alle/viele so machen ..... :roll:
Also ich fände die erste Idee fals machbar schon recht fein (bis jetzt ^^).

ichbins 11. Apr 2006 11:49

Re: Ruhezustand blockieren-> Versuch erkennen -> selbs
 
ich mach halt einfach eine boolean-Variable etwa so:

Delphi-Quellcode:
procedure getmessage;
begin
  if bool then exit;
  post(abbruchmessage);
  bool:=true;
  save;
  post(shutdownmessage);

ichbins 14. Mai 2006 20:24

Re: Ruhezustand blockieren-> Versuch erkennen -> selbs
 
Inzwischen bin ich so weit gekommen:
Delphi-Quellcode:
procedure TForm1.WMPowerBroadcast(var Msg: TWMPower);
begin
  showmessage('got message: wmpowerbroadcast');
  if ((msg.msg=PBT_APMQUERYSUSPEND) and (not readyforsuspend)) then
  begin
    showmessage('message is pbt_apmquerysuspend');
    Msg.Result := BROADCAST_QUERY_DENY;
    if messagedlg('denied. suspend?',mtinformation,[mbyes,mbno],0)=mryes then
      suspend(self);
  end else
    showmessage('message is not pbt_apmquerysuspend');
end;

procedure suspend(var form:tform1);
begin
  form.readyforsuspend:=true;
  form.closeallowed:=true;
  form.close;
  setsystempowerstate(true,false);
end;
Aber leider funktioniert das ganze nicht. Wenn ich den Ruhezustand auslöse, erhält er zwar die wmpowerbroadcast, aber erkennt nicht, dass es sich um eine pbt_apmquerysuspend handelt.

Olli 14. Mai 2006 20:44

Re: Ruhezustand blockieren-> Versuch erkennen -> selbs
 
Schreibe einen PnP-Treiber der den Ruhezustand nicht unterstützt und installiere ihn. Das funzt immer - den Ruhezustand gibt's dann nimmer.

Aber mal ernsthaft, kannst du das mit dem Verstecken der Daten nochmal genauer ausführen?!

BTW:
Zitat:

Zitat von Union
Das ist praktische Erfahrung. Und Windows wartet auch nicht auf jedes Programm. Sonst würde ja das Runterfahren verhindert durch Programme, die diese Message gar nicht verarbeiten.

Sowas gibt es natürlich nicht. Denn die Standardfensterroutine dürfte das wohl verarbeiten - und die ist schließlich an der Reihe wenn das eigene Programm eine Nachricht nicht verarbeitet.

ichbins 14. Mai 2006 20:47

Re: Ruhezustand blockieren-> Versuch erkennen -> selbs
 
@treiber: vielleicht eine Stufe zu brutal ;)


ich will den Ruhezustand ja nur verhindern, um dann meine Sachen zu speichern, was unter Umständen länger als 20 Sekunden dauern kann, und dann den Ruhezustand selbst auslösen, so dass es dem User nur "verzögert" scheint.

Nighthawk1310 14. Mai 2006 21:08

Re: Ruhezustand blockieren-> Versuch erkennen -> selbs
 
wo ist das problem?
verarbeite die message, sage nein zum supend, hibernate oder was auch immer.
speichere deine daten und entferne sie aus deiner anzeige, danach setzt du
eine boolean-variable auf true.
dann rufst du die funktion für den suspend/hibernate modus auf und
erlaubst bei erneuter messageverarbeitung anhand deiner vorher gesetzten variablen den suspend/hibernate.

das sollte die einfachste methode darstellen.

ichbins 14. Mai 2006 21:35

Re: Ruhezustand blockieren-> Versuch erkennen -> selbs
 
Das ist mir schon klar. Ich hab nur Probleme damit, zu Überprüfen, ob das WM_Powerbroadcast auch wegen dem Ruhezustand ausgelöst wurde und nicht wegen z.B. einem Reboot.


Diese Impementierung
Delphi-Quellcode:
 if msg.msg=PBT_APMQUERYSUSPEND then
scheint jedenfalls nicht zu funktionieren.

ichbins 15. Mai 2006 14:21

Re: Ruhezustand blockieren-> Versuch erkennen -> selbs
 
Ich habe jetzt eine Lösung für mein Problem gefunden und poste sie hier:


Oben in der Definition der Form müssen folgende 2 Einträge hinzugefügt werden:
Delphi-Quellcode:
procedure WMPowerBroadcast(var Msg: TWMPower); message WM_POWERBROADCAST
readyforsuspend:boolean;
Und im Code-Abschnitt die folgenden 3 Prozeduren:
Delphi-Quellcode:
function EnableShutDownPrivilege: Boolean;
var
  vi: TOSVersionInfo;
  hToken: THandle;
  tp: TTokenPrivileges;
  h: DWord;
begin
  result := False;
  vi.dwOSVersionInfoSize := SizeOf(vi);
  GetVersionEx(vi);
  if vi.dwPlatformId = VER_PLATFORM_WIN32_NT then // Windows NT
  begin
    OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, hToken);
    LookupPrivilegeValue(nil, 'SeShutdownPrivilege', tp.Privileges[0].Luid);
    tp.PrivilegeCount := 1;
    tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
    h := 0;
    result := AdjustTokenPrivileges(hToken, False, tp, 0,
      PTokenPrivileges(nil)^, h);
    CloseHandle(hToken);
  end;
end;

procedure TForm1.WMPowerBroadcast(var Msg: TWMPower);
begin
  if ((msg.powerevt=PBT_APMQUERYSUSPEND) and (not readyforsuspend)) then
  begin
    Msg.Result := BROADCAST_QUERY_DENY;
    readyforsuspend:=true;
    suspend(self);
  end;
end;

procedure suspend(var form:tform1) {die Variable form1 wird hier übertragen, damit auch von der Klassenunabhängigen Prozedur SUSPEND auf die form zugegriffen werden kann.});
begin
 
  {hier Speichervorgänge, wie das Schliesen des Forms etc. vornehmen. Sie dürfen beliebig lange dauern.}

  if enableshutdownprivilege then
    setsystempowerstate(true,false);
end;


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