c0d3r 17 Posted Sunday at 01:24 AM (edited) Hi, All Our client application used a timer (TTimer) to send a ping to our application server every 60 seconds. It seems that the timer being killed by Windows when entering the Modern Standby mode, and never being re-activated when exit. The big problem is that Windows seems never send notification to all the applications when entering/exit from the modern standby mode. any way we could restart the timer? BTW, We did register power notification call back, like this: var LParameters: DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS; LParameters.ACallback := @DeviceNotifyCallbackRoutine; LParameters.AContext := nil; PowerRegisterSuspendResumeNotification(DEVICE_NOTIFY_CALLBACK, @LParameters, @FPowerNotify); However, we never got any notifications from Windows, no entry/no exit notifications at all. Any help would be appreciated. Thanks. Regards, William Edited Sunday at 01:48 AM by c0d3r Share this post Link to post
Anders Melander 1894 Posted Sunday at 03:48 AM I think the timer is still alive. It just takes a (unusually long) while to fire after resume from standby. See also: https://github.com/cyd01/KiTTY/issues/475 Share this post Link to post
dwrbudr 8 Posted Sunday at 03:57 AM Try using RegisterPowerSettingNotification in combination with GUID_MONITOR_POWER_ON power setting GUID Share this post Link to post
c0d3r 17 Posted Sunday at 05:41 PM (edited) 13 hours ago, Anders Melander said: I think the timer is still alive. It just takes a (unusually long) while to fire after resume from standby. See also: https://github.com/cyd01/KiTTY/issues/475 I thought so, BUT there is no new PING records in the server database after exit from the standby, so I think the timer is dead completely (I was at least waiting for 5+ minutes to check). Edited Sunday at 05:51 PM by c0d3r Share this post Link to post
c0d3r 17 Posted Sunday at 05:45 PM 13 hours ago, dwrbudr said: Try using RegisterPowerSettingNotification in combination with GUID_MONITOR_POWER_ON power setting GUID Is this the new requirement for this? The regular Windows sleeping/wake up don't need this GUID, which was working just fine. Share this post Link to post
Anders Melander 1894 Posted Sunday at 06:33 PM 45 minutes ago, c0d3r said: there is no new PING records in the server database after exit from the standby You are looking at the symptoms at the end of a long chain of circumstances. You need to look at the other end, which supposedly (assuming WM_TIMER is the problem) is closer to the source of the problem. 33 minutes ago, c0d3r said: I think the timer is dead completely (I was at least waiting for 5+ minutes to check). If standby killed WM_TIMER then millions of applications would break so I think it's very unlikely. The bug in PuTTY wasn't that the timer didn't fire but that they assumed that it would fire with a certain time interval and WM_TIMER is never guaranteed to do that. AFAIK WM_TIMER is a low priority message which is only synthesized when the message queue is polled and no higher priority messages are in the queue (or synthesized). I don't know your application but it could be that the queue is simply flooded with other stuff after resume from standby. So instead of assuming that WM_TIMER doesn't work I recommend that you simply verify with a simple application that does nothing but write a time stamp to a TMemo every time a 1 second TTimer fires. If that doesn't work then there's a problem with TTimer and we can start examining what that is. 1 Share this post Link to post
c0d3r 17 Posted Sunday at 07:15 PM (edited) 40 minutes ago, Anders Melander said: So instead of assuming that WM_TIMER doesn't work I recommend that you simply verify with a simple application that does nothing but write a time stamp to a TMemo every time a 1 second TTimer fires. If that doesn't work then there's a problem with TTimer and we can start examining what that is. Good idea. will do it and report back. Edited Sunday at 07:19 PM by c0d3r Share this post Link to post
c0d3r 17 Posted Tuesday at 10:38 PM (edited) On 2/16/2025 at 1:33 PM, Anders Melander said: So instead of assuming that WM_TIMER doesn't work I recommend that you simply verify with a simple application that does nothing but write a time stamp to a TMemo every time a 1 second TTimer fires. If that doesn't work then there's a problem with TTimer and we can start examining what that is. Got the report back: TTimer was suspended and never resumed after exit from Modern standby mode (S0). It looks to me that all activities in the applications threads and windows message handlers were suspended, never being resumed. Edited Tuesday at 10:47 PM by c0d3r Share this post Link to post
Anders Melander 1894 Posted Tuesday at 10:54 PM Bummer. I've just checked both my desktop (which is a *ehem* 15 years old home build) and my laptop which is the top Lenovo X1 model, 2 years old, and neither of them support S0. This means that I unfortunately can't help debug the problem. If anyone else wants to have a go at it, the command to check for S0 support is powercfg /a. Note though that if Modern Standby isn't already enabled then it requires a complete OS reinstall to enable it. Yup, you read that right. Nice one, Microsoft. 1 Share this post Link to post
Remy Lebeau 1494 Posted Wednesday at 12:14 AM 1 hour ago, c0d3r said: It looks to me that all activities in the applications threads and windows message handlers were suspended, never being resumed. That is highly unlikely. If that were true, then all applications would be dead upon wakeup. I think you are misdiagnosing the problem. But, as I don't have an S0-enabled computer, I can't help you diagnose that better. Have you tried using the TApplication[Events].OnMessage event, and TApplication.HookMainWindow() and overriding the TForm.WndProc() method, to actually check that window messages are really no longer being processed? In any case, an application can detect support for Modern Standby by checking the AoAc field returned by GetPwrCapabilities(). And register for notification of Modern Standby/Resume using RegisterSuspendResumeNotification(). Share this post Link to post
c0d3r 17 Posted Wednesday at 01:07 AM 39 minutes ago, Remy Lebeau said: In any case, an application can detect support for Modern Standby by checking the AoAc field returned by GetPwrCapabilities(). And register for notification of Modern Standby/Resume using RegisterSuspendResumeNotification(). HI, Remy As stated in my post #1, we are using PowerRegisterSuspendResumeNotification, call back routine, but we get ZERO notification when entry/exit from Modern Standby/Resume (regular Windows sleeping/wake up is working fine). Any difference between PowerRegisterSuspendResumeNotification and your RegisterSuspendResumeNotification. As the sample code we use to test, very simple, a TTimer and a Memo field on a vcl form, and OnTimer event (every 1 second): procedure TForm1.Timer1Timer(Sender: TObject); begin Memo1.Lines.Add(TimeToStr(Now)); end; NO output in the memo field after exit from Modern StandBy mode. Share this post Link to post
c0d3r 17 Posted Wednesday at 01:24 AM 1 hour ago, Remy Lebeau said: Have you tried using the TApplication[Events].OnMessage event, and TApplication.HookMainWindow() and overriding the TForm.WndProc() method, to actually check that window messages are really no longer being processed? Yes. we did: WM_KEYFIRST..WM_KEYLAST, WM_MOUSEFIRST..WM_MOUSELAST, seems working. Share this post Link to post
Remy Lebeau 1494 Posted Wednesday at 02:06 AM (edited) 56 minutes ago, c0d3r said: Any difference between PowerRegisterSuspendResumeNotification and your RegisterSuspendResumeNotification. According to MSDN: Quote Similar to PowerRegisterSuspendResumeNotification, but [RegisterSuspendResumeNotification] operates in user mode and can take a window handle. Quote As the sample code we use to test, very simple, a TTimer and a Memo field on a vcl form, and OnTimer event (every 1 second): TTimer is based on a window-based WM_TIMER message. TTimer has an internal HWND that it receives WM_TIMER messages with. And TMemo is another window-based UI control. Are you ABSOLUTELY SURE that your app's message queue is not generating WM_TIMER messages? Never mind whether they are being DELIVERED to TTimer or TMemo - are they being GENERATED at all? The TApplication[Events].OnMessage event should be able to very that, since it sees all messages coming out of the main thread's message queue. Or even a tool like Spy++ or Winsight. For all we know, your windows got recreated and that is why messages are being lost. Who knows. Did you try verifying that the TTimer's HWND and the TMemo's HWND are still the same before the Standby and after the Wakeup? Quote NO output in the memo field after exit from Modern StandBy mode. You are looking at multiple things at one time which are acting on top of each other, and not verifying the behavior at the ROOT of the chain of actions. Edited Wednesday at 02:08 AM by Remy Lebeau Share this post Link to post
c0d3r 17 Posted Wednesday at 02:29 AM (edited) 20 minutes ago, Remy Lebeau said: For all we know, your windows got recreated and that is why messages are being lost. Who knows. Did you try verifying that the TTimer's HWND and the TMemo's HWND are still the same before the Standby and after the Wakeup? We don't see why windows got recreated and how to check HWND values before standby and after the wakeup, because we never know when its entering modern standby mode and when its waken up. Edited Wednesday at 02:30 AM by c0d3r Share this post Link to post
Lajos Juhász 311 Posted Wednesday at 04:06 AM 2 hours ago, c0d3r said: NO output in the memo field after exit from Modern StandBy mode. In my case the timer continues to fire after sleep. The following sleep states are available on this system: Standby (S0 Low Power Idle) Network Connected Hibernate Fast Startup Share this post Link to post
Remy Lebeau 1494 Posted Wednesday at 04:19 AM (edited) 1 hour ago, c0d3r said: We don't see why windows got recreated and how to check HWND values before standby and after the wakeup A TTimer HWND shouldn't change, but any VCL UI control can recreate for any number of reasons. Can't rule anything out at this point. Quote because we never know when its entering modern standby mode and when its waken up. So do it manually. Create a temporary button or something that you can trigger at will to log the current HWNDs, then invoke a standby+wakeup, then trigger the log again and compare the results. Edited Wednesday at 04:19 AM by Remy Lebeau 1 Share this post Link to post
Pat Foley 53 Posted Wednesday at 04:45 AM 15 minutes ago, Remy Lebeau said: Create a temporary button or something that you can trigger at will to log the current HWNDs, then invoke a standby+wakeup, then trigger the log again and compare the results. Here's my logger I had suspected some issue with timer restarting I wrapped the timer event to disable the timer when in the event seemed to help and removed a show event on the logging form seemed to have fixed. The following sleep states are available on this system: //Pats win 11 pro Standby (S0 Low Power Idle) Network Connected Hibernate Fast Startup The following sleep states are not available on this system: Standby (S1) The system firmware does not support this standby state. This standby state is disabled when S0 low power idle is supported. Standby (S2) The system firmware does not support this standby state. This standby state is disabled when S0 low power idle is supported. Standby (S3) This standby state is disabled when S0 low power idle is supported. Hybrid Sleep Standby (S3) is not available. The hypervisor does not support this standby state. //Events app1 sidebar memoShowMessages h18.834 ZeroIndex 985940 Comp 199704 18.835 TSideBar on top//1 18.838 Shell_TrayWnd on top // closing logged on App1 18.858 Windows.UI.Core.CoreWindow on top//opening App1 18.861 LockScreenControllerProxyWindow on top 18.861 Shell_TrayWnd on top 18.864 TSideBar on top //events Second running App sidebar memoShowMessages 18.826 TSideBar on top 18.827 CabinetWClass on top 18.829 Shell_TrayWnd on top 18.834 on top 18.834 TSideBar on top //1 18.838 Shell_TrayWnd on top// closing logged on App2 18.858 on top 18.859 Windows.UI.Core.CoreWindow on top//opening logged on App2 18.861 LockScreenControllerProxyWindow on top 18.861 Shell_TrayWnd on top 18.864 TSideBar on top // made with this coding var TopWinControl: HWND; procedure TSideBar.TaskTimerTimer(Sender: TObject); const MAX_VALUE = 255; var pcClassName: Array [0 .. MAX_VALUE] Of Char; aClassName: string; Hnd: HWND; begin TaskTimer.Enabled := False; Hnd := GetForegroundWindow; // shows apps being used. if Hnd <> TopWinControl then begin TopWinControl := Hnd; GetClassName(Hnd, pcClassName, MAX_VALUE); aClassName := Trim(pcClassName); label1.Caption := aClassName; memoShowMessages.Lines.add(format('%2.3f %s on top', [Time * 24, aClassName]));//Screen.Forms[0].Name]); end; // show now can change bringtofront getfocus best not use here //boo 100xs Jumper.Show; // not needed and perhaps fighting the debugger TaskTimer.Enabled := True; end; Needs to be 64 bit. 1 Share this post Link to post