How to pause Windows shutdown
Asked Answered
T

2

4

I need to mute/un-mute the sound card at startup and shutdown.

I have found some code to do the work, but often Windows slams through the shutdown and the sound never gets muted.

Can someone please tell me how to pause the shutdown long enough for my app to mute the sound? I can use a simple TTimer to pause the app long enough for it to run the muting and then let Windows get on with shutting down.

How do I tell Windows to wait though?

I notice that if I leave Firefox running and try to shutdown, Windows stops with a message, "These programs are preventing windows closing..." and needs a click to force Firefox to close. I need to find that.

Trulatrull answered 20/8, 2013 at 23:30 Comment(3)
How are you muting/unmuting sound card? I'm just guessing, but I think that process like that should be instantaneous, or atleast executed in matters of milliseconds. Other than that, IMHO, you should catch WM_QUERYENDSESSION or some similar message and do the muting process there.Mme
On what version of Windows is your application need to run?Alphonso
Win7 and win8 laptops. See more Comments below.Trulatrull
A
7

Since Windows Vista, if you register a shutdown reason string with the OS or if your application has a top level window, the OS will wait indefinitely for your program to return from WM_QUERYENDSESSION while displaying the blocking applications screen - or until the user chooses to forcefully end the program of course.

The below sample code simulates a 45 seconds wait with Sleep. In the first five seconds of the wait the OS waits patiently, only then it displays the full screen UI. The only way to show the screen immediately is to immediately return false from WM_QUERYENDSESSION. But in this case you won't be able to resume shutdown.

For details on shutdown behavior of the OS for Vista and later, see documentation.

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;
Alphonso answered 21/8, 2013 at 1:19 Comment(2)
This is the correct solution for Vista and later, but if you need to support XP or earlier then you will have to dynamically load ShutdownBlockReasonCreate() and ShutdownBlockReasonDestroy() using GetProcAddress() so your app will be able to run on versions earlier than Vista.Impressible
@SertacAkyuz and Remy, thanks. I will give this a try when I get home. More info in Comments below.Trulatrull
C
3

You need to handle the WM_QUERYENDSESSION messsage. It's sent to each application before Windows starts the shutdown process. Do what you need quickly, because failure to respond rapidly enough causes the behavior you're observing in FireFox, which is usually a sign of a badly designed app (and the user may terminate it before you get a chance to finish).

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;

(Just as an aside: The enabling/disabling of sounds is a per-user setting, and you should have a very good need for interfering with the user's choice. If I were you, I'd make sure my uninstaller was well-tested, because any app that interfered with my sound preferences this way would be removed from my system very quickly.)

Chalky answered 21/8, 2013 at 0:11 Comment(3)
Thank Ken, I will try that when I get home. It is for my personal use. I have a USB sound card for the laptop that feeds into a smallish stereo. It clicks and pops very loudly and I need to mute it at shut-down and un-mute it after it has all started up in the morning. I may need to actually disable the sound card, but will see if one of the above solutions solve the issue just with muting. I have tried several USB sound-cards and they all do it.Trulatrull
OK, problem is bigger than I thought. Both of those options seem to work, but the mmSystem code I fonud on the Swiss Delphi center does nothing. I can use the Mute button in Win Media center and it stays muted through Shut-down and start-up which is what I want to stop the pops. I need to build that functionality into a small program. Any thoughts on how to control the sound as windows does? Suggestions or pointers to code? Thanks.Trulatrull
That would be a separate question from this one. :-) This one is about "How to pause Windows shutdown", and Sertac and I both answered that one. If you now have a new question about controlling Windows sound, it should be posted as a new question. (You can reference this one as additional information if you'd like.) SO is based on asking a specific question and receiving answers to that question.Chalky

© 2022 - 2024 — McMap. All rights reserved.