Entwickler-Ecke

Windows API - Ruhezustand mit shellexecute und setsuspendstate


olliterski - Mi 23.04.08 22:22
Titel: Ruhezustand mit shellexecute und setsuspendstate
Nabend,

ich habe mir mal ein Programm geschrieben, mit dem man den Rechner in den Ruhezustand fahren kann.
Davon habe ich aber keinen Code ...rein garnichts mehr bis auf die EXE!

In den Ruhezustand komm ich ja, aber ich muss aus gewissen gründen noch ein LOGOFF einbauen für den aktuellen User!

Jetzt muss ich das Ding auch noch erweitern!
Nach langer suche, habe ich einige Codefetzen hier und da aufgeschnappt!
Meiner Meinung nach habe ich mir aber bei den Variablen einen Fehler eingebaut!

  1. Wer kann mir mal unter die Arme greifen?
  2. Hat jemand eine Ahnung wie man über die EXE an den Quelltext kommt? (FKT-Aufruf,Parameter, usw.)
  3. Hätte jemand die Möglichkeit, das mal für mich zu machen?


Muss gestehen, habe schon lange nichts mehr mit Delphi gemacht und bin ein 'wenig'
aus der Übung! ;o) (Stecke im Augenblick in ner 6-monatigen SAP-Schulung und kann
mich da jetzt auch nicht sonderlich reinknien! Hab einfach keine Zeit dafür...)


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,shellapi;

type
  TForm1 = class(TForm)
    procedure FormShow(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormShow(Sender: TObject);
begin
  shellexecute(application.Handle,
               'open',
               rundll32.exe powrprof.dll,SetSuspendState Hibernate',
               nil,
               nil,
               SW_SHOW);
  // shellexecute(rundll32.exe powrprof.dll,SetSuspendState Hibernate); //Orig!
  ////Erweiterung
  // Benutzer abmelden
  // ExitWindowsEx (EWX_LOGOFF, $FFFFFFFF);

  exit;
end;


jaenicke - Do 24.04.08 08:58
Titel: Re: Ruhezustand mit shellexecute und setsuspendstate
user profile iconolliterski hat folgendes geschrieben:
Hat jemand eine Ahnung wie man über die EXE an den Quelltext kommt? (FKT-Aufruf,Parameter, usw.)
Delphi-Quelltext? Gar nicht. Assembler-Quelltext? Das geht, hilft dir aber vermutlich nichts.

Zum Problem: Wenn du den aktuellen Benutzer abmeldest, wird auch dein Programm geschlossen, du hast dann rein von der Logik her gar nicht mehr die Möglichkeit, den PC in den Ruhezustand zu schicken.
Dafür müsste dein Programm auch ohne angemeldeten Benutzer laufen und das kann nur ein Service, der aber etwas komplizierter als ein normales Programm zu schreiben ist. Delphi hat dafür eine Vorlage "Service Anwendung" o.ä., die dir ein Grundgerüst dafür baut.


starsurfer - Do 24.04.08 10:39

ich hab gerade ein Programm erstellt was auch so was in der Art macht, benutzt hab ich folgendes:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
function TMainForm.SetSuspendState(Hibernate, ForceCritical,DisableWakeEvent: Boolean): Boolean;

  function LinkAPI(const module, functionname: string): Pointer;
  var
    hLib: HMODULE;
  begin
    hLib := GetModulehandle(PChar(module));
    if hLib = 0 then
       hLib := LoadLibrary(PChar(module));
    if hLib <> 0 then
       Result := getProcAddress(hLib, PChar(functionname))
    else
       Result := nil;
end;

begin
  if not Assigned(_SetSuspendState) then
    @_SetSuspendState := LinkAPI('POWRPROF.dll', 'SetSuspendState');
  if Assigned(_SetSuspendState) then
    Result := _SetSuspendState(Hibernate, ForceCritical,
      DisableWakeEvent)
  else
    Result := False;
end;


für Standby, Code ist glaube vom Delphi-Treff...


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
function TMainForm.ExWindows(const AFlag: Word): Boolean;
var
  vi     : TOSVersionInfo;
  hToken : THandle;
  tp     : TTokenPrivileges;
  h      : DWord;
begin
  result:= false;

  vi.dwOSVersionInfoSize:=SizeOf(vi);

  if GetVersionEx(vi) then
  begin
    if vi.dwPlatformId = VER_PLATFORM_WIN32_NT then
    begin
      // Windows NT
      if OpenProcessToken(GetCurrentProcess,TOKEN_ADJUST_PRIVILEGES,hToken) then
      begin
        LookupPrivilegeValue(nil,'SeShutdownPrivilege',tp.Privileges[0].Luid);
        tp.PrivilegeCount := 1;
        tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
        h := 0;
        AdjustTokenPrivileges(hToken,False,tp,0,PTokenPrivileges(nil)^, h);
        CloseHandle(hToken);
        result := ExitWindowsEx(Aflag, 0);
      end;
    end
    else
    begin // Windows 95
      Result := ExitWindowsEx(Aflag, 0);
    end;
  end;
end;

...

        ShutDown: ExWindows(EWX_Poweroff or EWX_FORCEIFHUNG);
        Restart : ExWindows(EWX_Reboot or EWX_FORCEIFHUNG);
        LogOut  : ExWindows(EWX_Logoff or EWX_FORCEIFHUNG);


für den Rest halt ;) (is glaube auch vom Delphi-Treff)


olliterski - Do 24.04.08 17:55

Hallo,

@jaenicke:

Also ich hatte es in Delphi 7 geschrieben, war aber kein Assembler!
Das ist ja das dumme - eine einzige Zeile mit shellexecute hatte gereicht ...ich krieg sie bloß nicht mehr zusammen!

Das mit dem Ausloggen und dem Beenden des Programms hat mir auch schon zu denken gegeben!
Allerdings ist mir da die Idee gekommen den Aufruf für den Ruhezustand eventuell als post-event auszuführen.

Funktioniert aber auch nur, wenn mit dem Ausloggen die Befehls-Pipe nicht aus dem Speicher geschmissen wird!

Viele Grüße

Oliver


Marc. - Do 24.04.08 18:19

user profile iconolliterski hat folgendes geschrieben:
Hallo,
@jaenicke:
Also ich hatte es in Delphi 7 geschrieben, war aber kein Assembler!

Dein Programm lässt sich jedoch immernoch in Assembler-Code aufspalten, d.h. disassemblern [http://de.wikipedia.org/wiki/Disassembler]. Allerdings ist es fraglich, ob Dir das etwas nutzen wird. ;)
Ich denke so hat es user profile iconjaenicke gemeint. :gruebel: