Советы по Delphi

       

Завершение работы Windows


Каким образом запустить процесс завершения работы операционной системы (функция ExitWindows) из кода моей программы? Мне необходимо перезапустить операционную систему без перезапуска компьютера.

Ok, приводим обе функции для перезапуска операционной системы:

procedure TMainForm.RestartWindowsBtnClick(Sender: TObject);beginif not ExitWindows(EW_RestartWindows, 0) thenShowMessage('Приложение не может завершить работу');end;



procedure TMainForm.RebootSystemBtnClick(Sender: TObject);beginif not ExitWindows(EW_RebootSystem, 0) thenShowMessage('Приложение не может завершить работу');end;

Функция ExitWindows не была правильно задокументирована Microsoft'ом и не содержит описания возвращаемого значения. Более того, информация о этой функции практически не встречается в других источниках. Вот правильное определение этой функции:

function ExitWindows (dwReturnCode: Longint;Reserved: Word): Bool;

Улучшения

Изменить данный совет мне помог , приславший письмо следующего содержания:

Хотелось бы внести некоторые дополнения с Ваш FAQ, которые касаются вопроса о завершении/перезагрузки Windows. Указанный код не даст результата для Windows NT (и даже, наверное, для Win2000). Ниже - корректно работающий код для Win9x и WinNT. Проверено под D4.

uses Windows;

procedure RebootSystem;
var
handle, ph: THandle;pid, n: DWORD;luid: TLargeInteger;priv: TOKEN_PRIVILEGES;dummy: PTokenPrivileges;ver: TOSVERSIONINFO;begin
ver.dwOSVersionInfoSize := Sizeof(ver);GetVersionEx(ver);if ver.dwPlatformId=VER_PLATFORM_WIN32_NT then beginpid := GetCurrentProcessId;if OpenProcessToken(ph, TOKEN_ADJUST_PRIVILEGES, handle) thenif LookupPrivilegeValue(nil, 'SeShutdownPrivilege', luid) then beginpriv.PrivilegeCount := 1;priv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;priv.Privileges[0].Luid := luid;dummy := nil;AdjustTokenPrivileges(handle, false, priv, 0, dummy^, n);end;end;ExitWindowsEx(EWX_REBOOT, 0);end;

уточняет:

К сожалению, 32-битная функция ExitWindowsEx не позволяет выполнить простой перезапуск Windows 95/98.

Тем не менее есть 16-битная функция ExitWindows, которая позволяет выполнить перезапуск, будучи вызванной с параметром EW_RESTARTWINDOWS.

Соответственно, в 32-битном приложении Вам либо нужно использовать Thunks, либо запускать дочернее 16-битное приложение, вызывающее данную функцию.


Даже если ты работаешь под Администратором, твоя программка должна запросить дополнительные привилегии. Вот как это делается (на языке Си):

void Reboot (void) { HANDLE hToken; TOKEN_PRIVILEGES* NewState; OSVERSIONINFO OSVersionInfo; OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); GetVersionEx (&OSVersionInfo); if (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) { OpenProcessToken (GetCurrentProcess (), TOKEN_ADJUST_PRIVILEGES, &hToken); NewState = (TOKEN_PRIVILEGES*) malloc (sizeof (TOKEN_PRIVILEGES) + sizeof (LUID_AND_ATTRIBUTES)); NewState->PrivilegeCount = 1; LookupPrivilegeValue (NULL, SE_SHUTDOWN_NAME, &NewState->Privileges[0].Luid); NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges (hToken, FALSE, NewState, NULL, NULL, NULL); free (NewState); CloseHandle (hToken); } ExitWindowsEx (EWX_REBOOT, 0); } Здесь иная редакция этой процедуры (на Паскале, без проверки версии ОС) -

Procedure Shutdown(Name:String; // Имя машины (\\SERVER)
Message:String; // СообщениеDelay:Integer; // Задержка перед рестартомRestart,CloseAll:Boolean);var
ph:THandle;tp,prevst:TTokenPrivileges;rl:DWORD;begin
OpenProcessToken(GetCurrentProcess,TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,ph);LookupPrivilegeValue(Nil,'SeShutdownPrivilege',tp.Privileges[0].Luid);tp.PrivilegeCount:=1;tp.Privileges[0].Attributes:=2;AdjustTokenPrivileges(ph,FALSE,tp,SizeOf(prevst),prevst,rl);InitiateSystemShutdown(PChar(name),PChar(Message),Delay,Restart,CloseAll);ShowMessage(SysErrorMessage(GetLastError)); // Результатend;
[000019]


Содержание раздела