May 10, 2023

Windows Shutdown

Windows Shutdown

시스템 셧다운
Shutdown the (local or remote) computer (with delay)

function TimedShutDown(Computer: string; Msg: string; Time: Word; Force: Boolean; Reboot: Boolean): Boolean;
var
  rl: Cardinal;
  hToken: Cardinal;
  tkp: TOKEN_PRIVILEGES;
begin
  //get user privileges to shutdown the machine, we are talking about win nt and 2k here
  if not OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken) then
    ShowMessage('Cannot open process token.')
  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('Error adjusting process privileges.');
    end
  else
    ShowMessage('Cannot find privilege value.');
  end;

  Result := InitiateSystemShutdown(PChar(Computer), PChar(Msg), Time, Force, Reboot)
end;

Prevent Windows shutdown until files saved

Windows가 종료 될 때 열려있는 모든 응용 프로그램에 WM_QueryEndSession이라는 메시지를 보냅니다. Delphi 애플리케이션에서이 메시지를 감지하고 적절한 조치를 취하려면 메시지 처리기를 작성하십시오. 해당 메시지 처리기의 정의를 응용 프로그램의 기본 양식에 대한 유닛의 개인 섹션에 두십시오 (아래 참조).

또한 데이터를 저장할지 여부를 나타내는 부울 (논리) 변수, 예를 들어 DataToBeSaved가 필요합니다. 프로그램 시작시와 데이터를 저장할 때마다이 변수를 False로 설정하십시오. 데이터가 변경 될 때마다 True로 설정하십시오. private 섹션에서 변수를 선언하겠습니다.

private
  { Private declarations }
  DataToBeSaved: Boolean;
  procedure WMQueryEndSession(var Msg: TWMQueryEndSession);
    message WM_QueryEndSession; // detect Windows shutdown message
  procedure SaveData; // routine to save data to disk
  // ...and so on

In the implementation section of the unit, add the following code:

// If necessary (if DataToBeSaved is True), delay the closing of Windows until
// your data are saved
procedure TForm1.WMQueryEndSession(var Msg: TWMQueryEndSession);
begin
  if DataToBeSaved then
    if MessageDlg('Windows is shutting down! First save data changes?',
         mtConfirmation, [mbYes, mbNo], 0) = mrYes then begin
      Msg.Result := 0; // disallow Windows from shutting down
      SaveData;
    end;
  Msg.Result := 1;     // allow Windows shutdown
end; 

// Set DataToBeSaved to False after saving data
procedure TForm1.SaveData;
begin
  // Save data to disk files
  // ...
  DataToBeSaved := False;
end;  

// At the start of the program, DataToBeSaved must be False
procedure TForm1.FormCreate(Sender: TObject);
begin
  DataToBeSaved := False;
end;

데이터가 변경 될 때마다 DataToBeSaved을 True로 설정하는 것을 잊지 마십시오.

응용 프로그램이 실행되는 동안 Windows가 닫힐 때 자동으로 데이터를 저장하려면 'Windows가 종료 중입니다!'라는 질문이있는 메시지 대화 상자를 생략하십시오! 먼저 데이터 변경 사항을 저장 하시겠습니까? ' 메시지 처리기의 코드는 다음과 같습니다.

procedure TForm1.WMQueryEndSession(var Msg: TWMQueryEndSession);
begin
  if DataToBeSaved then begin
    Msg.Result := 0; // stop Windows from shutting down
    SaveData;
  end;
  Msg.Result := 1; // allow Windows shutdown
end;

How do I manipulate the computer (shutdown, restart, etc)

To shutdown the system:

procedure machine_shutdown;
  const
    SE_SHUTDOWN_NAME = 'SeShutdownPrivilege';
  begin
    NTSetPrivilege(SE_SHUTDOWN_NAME, True);
    ExitWindowsEx(EWX_SHUTDOWN or EWX_FORCE, 0);
  end;

This code restarts a computer:

procedure machine_restart;
  const
    SE_SHUTDOWN_NAME = 'SeShutdownPrivilege';
  begin
    NTSetPrivilege(SE_SHUTDOWN_NAME, True);
    ExitWindowsEx(EWX_REBOOT or EWX_FORCE, 0);
  end;

This code logs off the current user:

procedure machine_logoff;
  const
    SE_SHUTDOWN_NAME = 'SeShutdownPrivilege';
  begin
    NTSetPrivilege(SE_SHUTDOWN_NAME, True);
    ExitWindowsEx(EWX_LOGOFF or EWX_FORCE, 0);
  end;

This code powers down the system. This is distinguished from the shut down command in that it will power off the system, while the shut down command will just put the computer to a point where it can be turned off.

This code powers down the system:

  procedure machine_poweroff;
    const
      SE_SHUTDOWN_NAME = 'SeShutdownPrivilege';
    begin
      if IsPwrShutdownAllowed then
        begin
          NTSetPrivilege(SE_SHUTDOWN_NAME, True);
          ExitWindowsEx(EWX_POWEROFF or EWX_FORCE, 0);
        end
      else
        MessageDlg('Soft Power Off not supported on this system.', mtWarning, [mbOK], 0);
    end;

To lock the workstation, requiring the password if set is:

function LockWorkStation: boolean; stdcall; external 'user32.dll' name 'LockWorkStation';

procedure machine_lock;
    begin
      if not LockWorkStation then
        MessageDlg('System not locked successfully.', mtWarning, [mbOK], 0);
    end;

Standby

function SetSuspendState(hibernate, forcecritical, disablewakeevent: boolean): boolean; stdcall; external 'powrprof.dll' name 'SetSuspendState';

function IsHibernateAllowed: boolean; stdcall; external 'powrprof.dll' name 'IsPwrHibernateAllowed';

function IsPwrSuspendAllowed: Boolean; stdcall; external 'powrprof.dll' name 'IsPwrSuspendAllowed';

function IsPwrShutdownAllowed: Boolean; stdcall; external 'powrprof.dll' name 'IsPwrShutdownAllowed';

To put the system into standby mode, do this:

procedure machine_standby;
  begin
    if IsPwrSuspendAllowed then
      SetSuspendState(false, false, false)
    else
      MessageDlg('System Standby not supported on this system.', mtWarning, [mbOK], 0);
  end;

To put the system into hibernate, do this:

procedure machine_hibernate;
  begin
    if IsHibernateAllowed then
      SetSuspendState(true, false, false)
    else
      MessageDlg('System Hibernate not supported on this system.', mtWarning, [mbOK], 0);
  end;