Understanding expected timers

There is something I don't understand about suitable timers. I've searched the web and read the specs on MSDN plus everything I could find on stackoverflow (like the link ), but my timers fire almost immediately after the PC stops.

To focus on the problem, I wrote a small test application using XE5 (64-bit) on Windows 7 and tried to duplicate the project found here: http://www.codeproject.com/Articles/49798/Wake-the-PC-from -standby-or-hibernation

I thought the problem was how I get the time, but I can't seem to find the problem.

The test application looks like this (very simple):

enter image description here

I declare the stream type as follows

type
   TWakeupThread    = class(TThread)
   private
     FTime:         LARGE_INTEGER;
  protected
     procedure      Execute; override;
  public
     constructor    Create(Time: LARGE_INTEGER);
  end;

      

...

constructor TWakeupThread.Create(Time: LARGE_INTEGER);
begin
  inherited Create(False);
  FreeOnTerminate:=True;
  FTime:=Time;
end;


procedure TWakeupThread.Execute;
var
   hTimer:     THandle;
begin
  // Create a waitable timer.
  hTimer:=CreateWaitableTimer(nil, True, 'WakeupThread');
  if (hTimer <> 0) then
  begin
     //CancelWaitableTimer(hTimer);
     if (SetWaitableTimer(hTimer, FTime.QuadPart, 0, nil, nil, True)) then
     begin
        WaitForSingleObject(hTimer, INFINITE);
     end;
     CloseHandle(hTimer);
  end;
end;

      

Now that the Set Timer button is clicked, I calculate the file time this way and create a stream.

procedure TForm1.btnSetTimerClick(Sender: TObject);
var
   iUTCTime : LARGE_INTEGER;
   SysTime  : _SystemTime;
   FTime    : _FileTime;
   hHandle  : THandle;
   dt       : TDateTime;
begin
   ReplaceDate(dt,uiDate.DateTime);
   ReplaceTime(dt,uiTime.DateTime);
   DateTimeToSystemTime(dt, SysTime);
   SystemTimeToFileTime(SysTime, FTime);
   LocalFileTimeToFileTime(FTime, FTime);
   iUTCTime.LowPart := FTime.dwLowDateTime;
   iUTCTime.HighPart := FTime.dwHighDateTime;
   TWakeupThread.Create(iUTCTime);
end;

      

This does not work. The timer seems to fire less than 2 minutes after the system goes into suspend mode regardless of the amount of time selected. Any guidance as to what I am doing wrong would be appreciated.

EDIT

Found this interesting command line tool that allows us to check expected timers. From the command, you can "see" the status of your pending timers by typing:

powercfg -waketimers

      

I can use this to confirm that my timers are set correctly. I can also use this to confirm that my timers are still running when the PC wakes up prematurely.

Using the same tool, you can get a list of devices that can wake up from sleep (mouse, keyboard, network in my case):

powercfg -devicequery wake_armed

      

On all systems tested, the "powercfg -lastwake" command returns the following, which I don't know how to decrypt:

Wake History Count - 1
Wake History [0]
   Wake Source Count - 0

      

I have both sleep and hibernate enabled on Windows and both will wake up after a few seconds. There is no keyboard and mouse activity, and we have no devices sending WOL (wake-on-lan) requests to these PCs.

I am wondering if I need something special when calling SetSuspendState; here's my code:

function SetSuspendState(Hibernate, ForceCritical, DisableWakeEvent: Boolean): Boolean;
//Hibernate = False : system suspends
//Hibernate = True : system hibernates
begin
  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;
procedure TForm1.btnSuspendClick(Sender: TObject);
begin
     SetSuspendState(True, False, False);
end;

      

+3


source to share


1 answer


The problem was not delphi or code related in any way. The problem was created with a Windows 7 feature that allows more than magic packs when WOL is enabled. Forcing Windows to only listen for magic packets solved the problem.

MS Link: http://support.microsoft.com/kb/941145



Thanks to everyone who tried to help, and especially David Heffernan, who hinted at the possibility that something else is awakening the computer.

+3


source







All Articles