Как приостановить выключение Windows

Мне нужно отключить / включить звук звуковой карты при запуске и завершении работы.

Я нашел какой-то код для выполнения этой работы, но часто Windows отключается, и звук никогда не отключается.

Может кто-нибудь сказать, пожалуйста, как приостановить выключение достаточно долго, чтобы мое приложение отключило звук? Я могу использовать простой TTimer, чтобы приостановить приложение на достаточно долгое время, чтобы оно отключило звук, а затем позволить Windows завершить работу.

Как мне сказать Windows подождать?

Я замечаю, что если я оставляю Firefox запущенным и пытаюсь завершить работу, Windows останавливается с сообщением "Эти программы предотвращают закрытие окон..." и требует щелчка, чтобы принудительно закрыть Firefox. Мне нужно найти это.

2 ответа

Начиная с Windows Vista, если вы регистрируете строку причины отключения в ОС или если ваше приложение имеет окно верхнего уровня, ОС будет бесконечно долго ждать, пока ваша программа вернется из WM_QUERYENDSESSION во время отображения экрана блокирующих приложений - или пока пользователь не решит принудительно завершить программу, конечно.

Приведенный ниже пример кода имитирует ожидание 45 секунд с Sleep, В первые пять секунд ожидания операционная система терпеливо ждет, только затем она отображает полноэкранный интерфейс. Единственный способ немедленно показать экран - это немедленно вернуть false из WM_QUERYENDSESSION, Но в этом случае вы не сможете возобновить выключение.

Подробнее о поведении выключения ОС для Vista и более поздних версий см. Документацию.

type
  TForm1 = class(TForm)
    ..
  protected
    procedure WMQueryEndSession(var Message: TWMQueryEndSession);
      message WM_QUERYENDSESSION;
    ..

...

function ShutdownBlockReasonCreate(hWnd: HWND; Reason: LPCWSTR): Bool;
    stdcall; external user32;
function ShutdownBlockReasonDestroy(hWnd: HWND): Bool; stdcall; external user32;


procedure TForm1.WMQueryEndSession(var Message: TWMQueryEndSession);
const
  ENDSESSION_CRITICAL = $40000000;
begin
  Message.Result := LRESULT(True);
  if ((Message.Unused and ENDSESSION_CRITICAL) = 0) then begin
    ShutdownBlockReasonCreate(Handle, 'please wait while muting...');

    Sleep(45000); // do your work here

    ShutdownBlockReasonDestroy(Handle);
  end;
end;

Вы должны справиться с WM_QUERYENDSESSION messsage. Оно отправляется каждому приложению до того, как Windows запускает процесс завершения работы. Делайте то, что вам нужно быстро, потому что неспособность ответить достаточно быстро вызывает поведение, которое вы наблюдаете в FireFox, что обычно является признаком плохо спроектированного приложения (и пользователь может прекратить его, прежде чем вы получите возможность завершить работу).

interface

...

type
  TForm1 = class(TForm)
    procedure WMQueryEndSession(var Msg: TWMQueryEndSession);
      message WM_QUERYENDSESSION;
  end;

implementation

procedure TForm1.WMQueryEndSession(var Msg: TWMQueryEndSession);
begin
  // Do what you need to do (quickly!) before closing
  Msg.Result := True; 
end;

(Напомним, что включение / отключение звуков является настройкой для каждого пользователя, и у вас должна быть очень хорошая потребность вмешиваться в выбор пользователя. На вашем месте я бы удостоверился, что мой деинсталлятор был хорошо протестирован потому что любое приложение, которое мешало моим звуковым настройкам таким образом, было бы очень быстро удалено из моей системы.)

Другие вопросы по тегам