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 Windows beenden und dabei Updates installieren (https://www.delphipraxis.net/185963-windows-beenden-und-dabei-updates-installieren.html)

TUX_der_Pinguin 22. Jul 2015 13:46

Windows beenden und dabei Updates installieren
 
Hallo DPler,

ich habe in meinem Programm (Kiosk-Anwendung) den Punkt Beenden, hierbei soll der Rechner heruntergefahren werden. Bisher habe ich das mit ShellExecute() und "shutdown -s -f -t 0" realisiert.
Dabei ist mir jedoch aufgefallen das keine Updates installiert werden falls welche heruntergeladen wurden.
Die Windows Update Einstellungen stehen auf "Updates herunterladen, aber Installation manuell durchführen". Es sollen nämlich die Updates erst beim Beenden installiert werden.

Jetzt habe ich im internet und auch hier im Forum gesucht und bin auf einen Thread von devidespe gestoßen der genau das Gegenteil wollte, nämlich herunterfahren ohne die Installation von Updates.

Also dachte ich mir nehme ich doch den Code und alles wäre geritzt aber nix da der Rechner fährt direkt runter. :?
Delphi-Quellcode:
function WindowsShutDown(Computer : string; Msg : string; Time: Word; Force : Boolean; Reboot: Boolean) : Boolean;
var rl, hToken : Cardinal;
    tkp : TOKEN_PRIVILEGES;
begin
  Result:=False;
  if not OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken) then
  ShowMessage('Fehler beim Windows-Shutdown aufgetreten.') else
  begin
    if LookupPrivilegeValue(nil, 'SeShutdownPrivilege', tkp.Privileges[0].Luid) then
    begin
      tkp.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;
      tkp.PrivilegeCount:=1;
      AdjustTokenPrivileges(hToken, False, tkp, 0, nil, rl);
      if GetLastError <> ERROR_SUCCESS then
      ShowMessage('Fehler beim Windows-Shutdown aufgetreten.') else
      begin
        Result:=InitiateSystemShutdown(PChar(Computer), PChar(Msg), Time, Force, Reboot);
        if Result = False then
        ShowMessage('Fehler beim Windows-Shutdown aufgetreten.');
      end;
    end else ShowMessage('Fehler beim Windows-Shutdown aufgetreten.');
  end;
end;
Jetzt ging es in dem Thread weiter und Jemand schlug die Funktion
Delphi-Quellcode:
InitiateShutdown()
vor mit dem Flag SHUTDOWN_INSTALL_UPDATES.

Mir gelingt es jedoch einfach nicht diese Funktion zu implementieren.
Delphi-Quellcode:
const
  SHUTDOWN_FORCE_OTHERS = $00000001;
  SHUTDOWN_FORCE_SELF = $00000002;
  SHUTDOWN_GRACE_OVERRIDE = $00000020;
  SHUTDOWN_HYBRID = $00000200;
  SHUTDOWN_INSTALL_UPDATES = $00000040;
  SHUTDOWN_NOREBOOT = $00000010;
  SHUTDOWN_POWEROFF = $00000008;
  SHUTDOWN_RESTART = $00000004;
  SHUTDOWN_RESTARTAPPS = $00000080;

type
  function InitiateShutdown(lpMachineName, lpMessage: LPWSTR; dwGracePeriode, dwShutdownFlags, dwReason: DWORD): DWORD; stdcall;

implementation

  function InitiateShutdown; external advapi32 name 'InitiateShutdown';
Die Entwicklung geschieht in Delphi 2009 unter Windows XP, die Software wird jedoch nur auf Windows 7 Rechner eingesetzt.

Hat jemand eine Idee was ich falsch mache bzw. eine Idee woran es liegen kann das man beim herunterfahren die Updates nicht installiert werden?

baumina 22. Jul 2015 14:02

AW: Windows beenden und dabei Updates installieren
 
Zitat:

Zitat von TUX_der_Pinguin (Beitrag 1309526)
Mir gelingt es jedoch einfach nicht diese Funktion zu implementieren.

Wie und wo hast du denn den Aufruf von InitiateShutdown in Deinem Code drinstehen und welche Fehlermeldungen hattest du dadurch?

TUX_der_Pinguin 22. Jul 2015 14:32

AW: Windows beenden und dabei Updates installieren
 
Ich habe den Fehler selbst schon gefunden, die function 'InitiateShutdown' existiert nicht in der Advapi32.dll sondern nur die beiden Ansi und Unicode varianten 'InitiateShutdownA' und 'InitiateShutdownW'.

Mit folgender Implementierung hat es geklappt, und scheinbar werden jetzt auch die Updates beim Beenden installiert.
Delphi-Quellcode:
const
  SHUTDOWN_FORCE_OTHERS = $00000001;
  SHUTDOWN_FORCE_SELF = $00000002;
  SHUTDOWN_GRACE_OVERRIDE = $00000020;
  SHUTDOWN_HYBRID = $00000200;
  SHUTDOWN_INSTALL_UPDATES = $00000040;
  SHUTDOWN_NOREBOOT = $00000010;
  SHUTDOWN_POWEROFF = $00000008;
  SHUTDOWN_RESTART = $00000004;
  SHUTDOWN_RESTARTAPPS = $00000080;

type
  TInitiateShutdown = function(
  {$IFDEF UNICODE}
    lpMachineName, lpMessage: PWideChar;
  {$ELSE}
    lpMachineName, lpMessage: PAnsiChar;
  {$ENDIF}
    dwGracePeriode, dwShutdownFlags, dwReason: DWORD): DWORD; stdcall;
 
function InitiateShutdownA(lpMachineName, lpMessage: PAnsiChar; dwGracePeriode, dwShutdownFlags, dwReason: DWORD): DWORD; stdcall;
function InitiateShutdownW(lpMachineName, lpMessage: PWideChar; dwGracePeriode, dwShutdownFlags, dwReason: DWORD): DWORD; stdcall;


var
InitiateShutdown: TInitiateShutdown =
  {$IFDEF UNICODE}
    InitiateShutdownW;
  {$ELSE}
    InitiateShutdownA;
  {$ENDIF}

implementation

function InitiateShutdownA; external advapi32 name 'InitiateShutdownA';
function InitiateShutdownW; external advapi32 name 'InitiateShutdownW';
Mal schauen welche Überraschung Windows noch bereit behält :tongue:

zagota 22. Jul 2015 14:34

AW: Windows beenden und dabei Updates installieren
 
Zitat:

Zitat von TUX_der_Pinguin (Beitrag 1309526)
Hallo DPler,
function InitiateShutdown; external advapi32 name 'InitiateShutdown';[/DELPHI]Die Entwicklung geschieht in Delphi 2009 unter Windows XP,

In der Hilfe steht: Requires Windows Vista.

cu

Sir Rufo 22. Jul 2015 14:47

AW: Windows beenden und dabei Updates installieren
 
Zitat:

Zitat von zagota (Beitrag 1309535)
Zitat:

Zitat von TUX_der_Pinguin (Beitrag 1309526)
Hallo DPler,
function InitiateShutdown; external advapi32 name 'InitiateShutdown';[/DELPHI]Die Entwicklung geschieht in Delphi 2009 unter Windows XP,

In der Hilfe steht: Requires Windows Vista.

cu

Das macht doch nichts, denn die Software wird ja nur auf Systemen mit Win7 genutzt ;)

Sir Rufo 22. Jul 2015 14:49

AW: Windows beenden und dabei Updates installieren
 
@TUX_der_Pinguin

Schau doch mal in deinem Delphi in der Windows Unit nach, wie Emba diese Umleitung der API-Calls macht (Ansi/Unicode). Das ist dort wesentlich eleganter gelöst ;)

TUX_der_Pinguin 22. Jul 2015 15:27

AW: Windows beenden und dabei Updates installieren
 
Zitat:

Zitat von Sir Rufo (Beitrag 1309539)
@TUX_der_Pinguin

Schau doch mal in deinem Delphi in der Windows Unit nach, wie Emba diese Umleitung der API-Calls macht (Ansi/Unicode). Das ist dort wesentlich eleganter gelöst ;)

Vielen dank für den Tipp Sir Rufo, dass wirkt in der Tat etwas eleganter ;-)

Delphi-Quellcode:
function InitiateShutdown(lpMachineName, lpMessage: PWideChar; dwGracePeriode, dwShutdownFlags, dwReason: DWORD): DWORD; stdcall;
{$EXTERNALSYM InitiateShutdown}
function InitiateShutdownA(lpMachineName, lpMessage: PAnsiChar; dwGracePeriode, dwShutdownFlags, dwReason: DWORD): DWORD; stdcall;
{$EXTERNALSYM InitiateShutdownA}
function InitiateShutdownW(lpMachineName, lpMessage: PWideChar; dwGracePeriode, dwShutdownFlags, dwReason: DWORD): DWORD; stdcall;
{$EXTERNALSYM InitiateShutdownW}

implementation

function InitiateShutdown; external advapi32 name 'InitiateShutdownW';
function InitiateShutdownA; external advapi32 name 'InitiateShutdownA';
function InitiateShutdownW; external advapi32 name 'InitiateShutdownW';

Sir Rufo 22. Jul 2015 15:57

AW: Windows beenden und dabei Updates installieren
 
Ich würde es noch so abändern:
Delphi-Quellcode:
function InitiateShutdown(lpMachineName, lpMessage: PChar {PWideChar}; dwGracePeriode, dwShutdownFlags, dwReason: DWORD): DWORD; stdcall;
{$EXTERNALSYM InitiateShutdown}
function InitiateShutdownA(lpMachineName, lpMessage: PAnsiChar; dwGracePeriode, dwShutdownFlags, dwReason: DWORD): DWORD; stdcall;
{$EXTERNALSYM InitiateShutdownA}
function InitiateShutdownW(lpMachineName, lpMessage: PWideChar; dwGracePeriode, dwShutdownFlags, dwReason: DWORD): DWORD; stdcall;
{$EXTERNALSYM InitiateShutdownW}

implementation

function InitiateShutdown; external advapi32 name {$IFDEF UNICODE}'InitiateShutdownW'{$ELSE}'InitiateShutdownA'{$ENDIF};
function InitiateShutdownA; external advapi32 name 'InitiateShutdownA';
function InitiateShutdownW; external advapi32 name 'InitiateShutdownW';
Und jetzt hat man eine automatische Umleitung bei der Verwendung von
Delphi-Quellcode:
InitiateShutdown();

Der schöne Günther 22. Jul 2015 16:21

AW: Windows beenden und dabei Updates installieren
 
Ich habe bis heute nie verstanden was das für einen Sinn macht die Deklarationen in zwei Teile (Interface und implementation) aufzusplitten. Warum macht man das?

Sir Rufo 22. Jul 2015 17:09

AW: Windows beenden und dabei Updates installieren
 
Weil man es kann :mrgreen:

Hat wohl eher etwas mit der Übersichtlichkeit zu tun wenn das
Delphi-Quellcode:
; external advapi32 name 'InitiateShutdownA';
nicht auch noch in der Zeile steht.

Ansonsten ist es wurscht ...

boeseboese 23. Nov 2015 15:14

AW: Windows beenden und dabei Updates installieren
 
Hallo,

wäre evtl. jemand so freundlich das geschilderte Programm in der kompletten endgültigen Fassung zu quoten, so dass man es seinem Compiler vor die Füße werfen kann?

Danke und Gruß
boese²

TUX_der_Pinguin 24. Nov 2015 09:50

AW: Windows beenden und dabei Updates installieren
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von boeseboese (Beitrag 1322260)
Hallo,

wäre evtl. jemand so freundlich das geschilderte Programm in der kompletten endgültigen Fassung zu quoten, so dass man es seinem Compiler vor die Füße werfen kann?

Danke und Gruß
boese²

Hier ein kleines Programm welches nur den Rechner veranlasst herunterzufahren. Es sollten dann auch die Updates installiert werden.
Im Anhang befindet sich die Projekt Dateien samt Quelltext und EXE-File.

Delphi-Quellcode:
unit Unit1;

interface

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

type
  TForm15 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form15: TForm15;

implementation

uses Unit2;

{$R *.dfm}

procedure TForm15.Button1Click(Sender: TObject);
begin
  WindowsShutDown(nil, nil, 0, True, False);
end;

end.
Delphi-Quellcode:
unit Unit2;

interface
uses
  Windows,
  SysUtils;

const
  SHUTDOWN_FORCE_OTHERS = $00000001;
  SHUTDOWN_FORCE_SELF = $00000002;
  SHUTDOWN_GRACE_OVERRIDE = $00000020;
  SHUTDOWN_HYBRID = $00000200;
  SHUTDOWN_INSTALL_UPDATES = $00000040;
  SHUTDOWN_NOREBOOT = $00000010;
  SHUTDOWN_POWEROFF = $00000008;
  SHUTDOWN_RESTART = $00000004;
  SHUTDOWN_RESTARTAPPS = $00000080;

function WindowsShutDown(Computer: PChar; Msg: PChar; Time: Word; Force: Boolean; Reboot: Boolean): Boolean;
function InitiateShutdown(lpMachineName, lpMessage: PWideChar; dwGracePeriode, dwShutdownFlags, dwReason: DWORD): DWORD; stdcall;
{$EXTERNALSYM InitiateShutdown}
function InitiateShutdownA(lpMachineName, lpMessage: PAnsiChar; dwGracePeriode, dwShutdownFlags, dwReason: DWORD): DWORD; stdcall;
{$EXTERNALSYM InitiateShutdownA}
function InitiateShutdownW(lpMachineName, lpMessage: PWideChar; dwGracePeriode, dwShutdownFlags, dwReason: DWORD): DWORD; stdcall;
{$EXTERNALSYM InitiateShutdownW}

implementation

function InitiateShutdown; external advapi32 name {$IFDEF UNICODE}'InitiateShutdownW'{$ELSE}'InitiateShutdownA'{$ENDIF};
function InitiateShutdownA; external advapi32 name 'InitiateShutdownA';
function InitiateShutdownW; external advapi32 name 'InitiateShutdownW';

function WindowsShutDown(Computer: PChar; Msg: PChar; Time: Word; Force: Boolean; Reboot: Boolean): Boolean;
var
  rl: Cardinal;
  hToken: Cardinal;
  tkp: TOKEN_PRIVILEGES;
  flags: DWORD;

begin
  Result:=False;
  if not OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken) then
    RaiseLastOSError
  else
  begin
    if LookupPrivilegeValue(nil, 'SeShutdownPrivilege', tkp.Privileges[0].Luid) then
    begin
      tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
      tkp.PrivilegeCount := 1;
      AdjustTokenPrivileges(hToken, False, tkp, 0, nil, rl);
      if GetLastError <> ERROR_SUCCESS then
        RaiseLastOSError
      else
      begin

        if Win32MajorVersion >= 6 then
        begin
          //Flags
          if Reboot then
            flags := SHUTDOWN_FORCE_SELF or SHUTDOWN_GRACE_OVERRIDE or SHUTDOWN_RESTART
          else
            flags := SHUTDOWN_FORCE_SELF or SHUTDOWN_GRACE_OVERRIDE or SHUTDOWN_INSTALL_UPDATES;

          //Befehl ausführen
          if InitiateShutdown(Computer, Msg, Time, flags, 0) = ERROR_SUCCESS then
            result := True
          else
            RaiseLastOSError;
        end
        else
        begin
          if InitiateSystemShutdown(Computer, Msg, Time, Force, Reboot) then
            result := True
          else
            RaiseLastOSError;
        end;{else}

      end;{else}
    end
    else
      RaiseLastOSError;
  end;{else}

end;

end.

boeseboese 24. Nov 2015 10:36

AW: Windows beenden und dabei Updates installieren
 
Hey,

vielen Dank für die Antwort.

Das Programm hat tatsächlich die Windows Mimik angeschmissen und beim Herunterfahren Updates installiert.

Damit ich das Programm aber nun in meiner Aufgabenplanung nutzen kann bräuchte ich eine direkte Ausführung des Befehls bei Aufruf der *.exe ohne Umweg über die GUI bzw. einen entsprechenden Schalter.

Wärst du nochmal so freundlich?

Gruß
boese²

TUX_der_Pinguin 24. Nov 2015 13:28

AW: Windows beenden und dabei Updates installieren
 
Liste der Anhänge anzeigen (Anzahl: 1)
Das Forum soll ja eigentlich nur als eine Art Hilfestellung dienen und nicht das andere einem die Arbeit abnehmen.
Aus dem Beispiel Programm eine Konsolen Anwendung zu erstellen die beim Aufruf direkt den Befehl ausführt ist nur eine Sache von ein paar Minuten.

Aber ich will heute mal nicht so sein und habe so eine kleine Konsolen Anwendung erstellt, die sich mit den entsprechenden Parametern aufrufen lässt.

Über Folgenden Befehl fährt der Rechner herunter und sollte dabei die Updates installieren...
Zitat:

WinShutdown -s -f

boeseboese 24. Nov 2015 14:27

AW: Windows beenden und dabei Updates installieren
 
Hi,

vielen Dank für die Bereitstellung.

Leider habe ich weder die Umgebung dafür den Code zu kompilieren noch das Know-How Anpassungen daran vorzunehmen.

Ich hatte halt nur das Glück beim Forschen nach einer Lösung über "InitiateShutdown" gestolpert zu sein und dann noch mehr Glück, dass hier jemand mit Programmier-Erfahrung in dem Bereich das gleiche Vorhaben hatte.

Nochmals vielen Dank für die Bereitstellung dieser Lösung.

Gruß
boese²

TUX_der_Pinguin 27. Nov 2015 11:27

AW: Windows beenden und dabei Updates installieren
 
Liste der Anhänge anzeigen (Anzahl: 1)
So Version 1.0.1 mit optimiertem Code.

TUX_der_Pinguin 2. Dez 2015 12:52

AW: Windows beenden und dabei Updates installieren
 
Liste der Anhänge anzeigen (Anzahl: 1)
Version 1.0.2 mit 'SeRemoteShutdownPrivilege' anstatt von 'SeShutdownPrivilege'


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