Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как отменить завершение работы Windows? ... чтобы инициировать новое? 
:(
    Опции темы
vovams
Дата 20.5.2009, 22:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 28.6.2007

Репутация: нет
Всего: нет



Мне нужно выключить компьютер так, чтобы пользователь не смог отменить выключение, но и чтобы не потерять несохранённые данные.
Решил сделать так: выключить компьютер API функцией ExitWindowsEx(EWX_SHUTDOWN) (т.е. не завершать приложения, которые ответили отказом на WM_QUERYENDSESSION), если компьютер не выключится через 30 секунд, сгибернировать его (спящий режим с сохранением RAM на HDD).

Теперь проблема. Если какое-то приложение имеет несохранённые данные, оно выдаёт запрос на сохранение. Если ничего не нажимать, то появится диалоговое окно снятия процесса (в Windows XP,  по крайней мере). Если пользователь нажмёт "Отмена" в первом запросе, или "Отмена" или "Снять процесс" во втором запросе, то всё сработает. Но вот если пользователь просто проигнорирует предложение снять процесс, свернёт его и продолжит работать, то моя программа повиснет при попытки сгибернировать компьютер.

Вот код функций выключения и гибернации (скачал из интернета):
Код

function LinkAPI(const module, functionname: string): Pointer; forward;
function SetSuspendState(Hibernate, ForceCritical,DisableWakeEvent: Boolean): Boolean;forward;
function MyExitWindows(RebootParam: Longword): Boolean;forward;

function MyExitWindows;
var
  TTokenHd: THandle;  
  TTokenPvg: TTokenPrivileges;  
  cbtpPrevious: DWORD;  
  rTTokenPvg: TTokenPrivileges;  
  pcbtpPreviousRequired: DWORD;  
  tpResult: Boolean;  
const  
  SE_SHUTDOWN_NAME = 'SeShutdownPrivilege';  
begin  
  if Win32Platform = VER_PLATFORM_WIN32_NT then  
  begin  
    tpResult := OpenProcessToken(GetCurrentProcess(),  
      TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,  
      TTokenHd);  
    if tpResult then  
    begin  
      tpResult := LookupPrivilegeValue(nil,  
                                       SE_SHUTDOWN_NAME,  
                                       TTokenPvg.Privileges[0].Luid);  
      TTokenPvg.PrivilegeCount := 1;  
      TTokenPvg.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;  
      cbtpPrevious := SizeOf(rTTokenPvg);  
      pcbtpPreviousRequired := 0;  
      if tpResult then  
        Windows.AdjustTokenPrivileges(TTokenHd,  
                                      False,  
                                      TTokenPvg,  
                                      cbtpPrevious, 
                                      rTTokenPvg, 
                                      pcbtpPreviousRequired); 
    end; 
  end; 
  Result := ExitWindowsEx(RebootParam, 0);
end;

{ 
  The SetSuspendState function suspends the system by shutting power down. 
  Depending on the Hibernate parameter, 
  the system either enters a suspend (sleep) state or hibernation. 

  Syntax: 
}
 {
  function SetSuspendState(
    Hibernate: Boolean;
    ForceCritical: Boolean;
    DisableWakeEvent: Boolean);
  }

 {  Parameters: 

   Hibernate: If this parameter is TRUE, the system hibernates. 
              If the parameter is FALSE, the system is suspended. 
   ForceCritical: If this parameter is TRUE, the system suspends operation immediately; 
                  if it is FALSE, the system broadcasts a PBT_APMQUERYSUSPEND event to 
                  each application to request permission to suspend operation. 
   DisableWakeEvent: If this parameter is TRUE, the system disables all wake events. 
                     If the parameter is FALSE, any system wake events remain enabled. 


  Windows NT/2000/XP: Included in Windows 2000 and later. 
  Windows 95/98/Me: Included in Windows 98 and later. 
}

 {var
   _SetSuspendState: function (Hibernate, ForceCritical, DisableWakeEvent: BOOL): BOOL
   stdcall = nil;                                                                     }



 function SetSuspendState(Hibernate, ForceCritical,
   DisableWakeEvent: Boolean): Boolean;
 var
   _SetSuspendState: function (Hibernate, ForceCritical, DisableWakeEvent: BOOL): BOOL
   stdcall ;

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

 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;

// Я вызываю так
MyExitWindows(EWX_SHUTDOWN);
// Потом
SetSuspendState(true,true,false);

Я так понимаю, что Windows не даёт инициировать новое завершение работы, пока активно старое. Если перед тем, как гибернировать, отменить выключение, то, наверное, должно сработать.

Подскажите, как сделать?
PM MAIL   Вверх
Keeper89
Дата 20.5.2009, 22:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2580
Регистрация: 26.2.2009

Репутация: 14
Всего: 58



vovams, данные нужно не потерять в сторонних приложениях?
P.S. Может проще дать пользователям время на сохранение, минуту например, а потом принудительно выключать компьютер?


--------------------
PM MAIL WWW   Вверх
bems
Дата 21.5.2009, 16:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 21
Всего: 88



попробуй отправить всем WM_QUERYENDSESSION и проанализировать результат. Если кто-то отказался  - в хибернейт


--------------------
Обижено школьников: 8
PM MAIL   Вверх
vovams
Дата 21.5.2009, 21:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 28.6.2007

Репутация: нет
Всего: нет



Цитата(Keeper89 @  20.5.2009,  22:44 Найти цитируемый пост)
vovams, данные нужно не потерять в сторонних приложениях?
P.S. Может проще дать пользователям время на сохранение, минуту например, а потом принудительно выключать компьютер?

Ну, да, нужно.
Нет, так не подойдёт: можно не успеть или не заметить предупреждение. Последний раз, когда программа выдавала предупреждение за минуту, а затем выключала принудительно, одна программа как-раз сохраняла данные, когда компьютер выключился, и все данные были потеряны.

Цитата(bems @  21.5.2009,  16:28 Найти цитируемый пост)
попробуй отправить всем WM_QUERYENDSESSION и проанализировать результат. Если кто-то отказался  - в хибернейт 

А если программа, получившая сигнал, выдаёт запрос на сохранение на экран и пользователь его проигнорирует, какой-то таймаут можно поставить? (И вообще, как это сделать?)
PM MAIL   Вверх
Keeper89
Дата 21.5.2009, 23:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2580
Регистрация: 26.2.2009

Репутация: 14
Всего: 58



Цитата(vovams @  21.5.2009,  21:42 Найти цитируемый пост)
А если программа, получившая сигнал, выдаёт запрос на сохранение на экран и пользователь его проигнорирует, какой-то таймаут можно поставить? (И вообще, как это сделать?) 

Как только пользователь отреагирует - гибернация. А таймер, думаю, можно поставить после получения положительного результата WM_QUERYENDSESSION.


--------------------
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.0444 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.