Entwickler-Ecke

Windows API - ...Windows beenden/neustarten?


Tino - Do 06.03.03 17:38
Titel: ...Windows beenden/neustarten?
Die Win32 API Funktion ExitWindowsEx zur Verfügung. Durch die Übergage verschiedener Parameter lässt sich ExitWindowsEx so ausführen, dass Windows beendet [meta]herunterfahren, runterfahren[/meta], neu gestartet oder der angemeldete Benutzer abgemeldet [meta]abmelden[/meta] werden kann. Damit Windows auf bestimmten Boards den PC ausschalten kann, muss das Flag EWX_POWEROFF gesetzt werden.

Unter Windows NT muss zusätzlich mit der Win32 API Funktion AdjustTokenPrivileges noch das Privileg SE_SHUTDOWN_NAME gesetzt werden, ansonsten lässt sich ExitWindowsEx nicht erfolgreich ausführen.

Kommen wir zu der Funktion ExitWindowsEx. Diese erwartet zwei Parameter:
Damit sie die Funktion und die Flag-Konstanten benutzen können müssen sie die Unit Windows in der Uses-Klausel aufnehmen. Hier mal ein paar Beispiel wie ExitWindowsEx aufgerufen werden kann:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
// Windows runterfahren
ExitWindowsEx (EWX_SHUTDOWN, $FFFFFFFF);

// Windows runterfahren und Computer ausschalten
ExitWindowsEx (EWX_SHUTDOWN or EWX_POWEROFF, $FFFFFFFF);

// Windows neustarten
ExitWindowsEx (EWX_REBOOT, $FFFFFFFF);

// Benutzer abmelden
ExitWindowsEx (EWX_LOGOFF, $FFFFFFFF);

Wie oben schon kurz beschrieben muss man unter Windows NT ein bestimmtes Privilig setzen damit der Aufruf der Funktion ExitWindowsEx Wirkung zeigt.

Um die Arbeit mit ExitWindowsEx, dem setzen des Privilig und den Flags zu vereinfachen habe ich im folgenden eine Fuktion gepostet welche die Funktion ExitWindowsEx aufruft und wenn nötig unter Windows NT das Privilig setzt. Außerdem erwartet die Funktion einen Aufzählungstypen (statt den Flags) als Paramter.

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:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
uses
  Windows;

type
  TShutdownWindowsType = (swtShutdown, swtShutdownPowerOff, swtRestart, swtLogoff);

function ShutdownWindows (aType: TShutdownWindowsType): Boolean;

{...}

function ShutdownWindows (aType: TShutdownWindowsType): Boolean;

const
  cSE_SHUTDOWN_NAME = 'SeShutdownPrivilege';
  cFlagValue: Array [TShutdownWindowsType] Of UINT = (
      EWX_SHUTDOWN, EWX_SHUTDOWN or EWX_POWEROFF, EWX_REBOOT, EWX_LOGOFF
    );

var
  OSVersionInfo: TOSVersionInfo;
  hToken: THandle;
  hProcess: THandle;
  TokenPriv: TTokenPrivileges;
  ReturnLength: DWORD;

begin
  Result := False;

  // Die Windowsversion holen
  OSVersionInfo.dwOSVersionInfoSize := SizeOf (OSVersionInfo);
  if not GetVersionEx (OSVersionInfo) then
    Exit;

  // Prüfen ob Windows NT
  if OSVersionInfo.dwPlatformId = VER_PLATFORM_WIN32_NT then
    begin
      hProcess := GetCurrentProcess;
      if not OpenProcessToken (hProcess, TOKEN_ADJUST_PRIVILEGES, hToken) then
        Exit;

      if not LookupPrivilegeValue (nil, cSE_SHUTDOWN_NAME, TokenPriv.Privileges[0].Luid) then
        Exit;

      TokenPriv.PrivilegeCount := 1;
      TokenPriv.Privileges [0].Attributes := SE_PRIVILEGE_ENABLED;

      if not AdjustTokenPrivileges (
          hToken, False, TokenPriv, 0,
          PTokenPrivileges (nil)^, ReturnLength
        )
      then
        Exit;

      CloseHandle (hToken);
    end;

  ShutdownWindows := ExitWindowsEx (cFlagValue [aType], $FFFFFFFF);
end;


Moderiert von user profile iconChristian S.: Meta-Tags hinzugefügt