There's something I don't understand about waitable timers. I searched online and read specs on MSDN plus whatever I could find on stackoverflow (such as link) but my timers fire almost immediately after the PC is suspended.
To focus on the problem I wrote a small test app using XE5 (64-bit) in 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 the way I derive time but I can't seem to find the problem.
The test app looks like this (very simple):
I declare the thread 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 when the "Set timer" button is clicked I calculate file time this way and create the thread.
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 then 2 minutes after the system enters suspend mode regardless of the amount of time selected. Any pointers as to what I am doing wrong would be appreciated.
EDIT
Found this interesting command line tool that let's us inspect the waitable timers. From command you can "see" the state of your waitable timers by typing:
powercfg -waketimers
I can use this to confirm that my timers are being set properly. I can also use this to confirm that my timers are still running when the PCs prematurely wake-up.
Using the same tool you can get a list of devices that are able to wake from hibernation (mouse, keyboard, network in my case):
powercfg -devicequery wake_armed
On all systems tested, the command "powercfg -lastwake" returns the following which I do not know how to decipher:
Wake History Count - 1
Wake History [0]
Wake Source Count - 0
I enabled both sleep and hibernate in Windows and both will wake up after a few seconds. There's no keyboard / mouse activity and we don't have devices sending WOL (wake-on-lan) requests to these PCs.
I'm wondering if there's something special I need to do 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;
The problem was not related to delphi or the code in any way. The problem was created by a Windows 7 feature that enables more than magic packets when WOL is enabled. Forcing Windows to only listen for magic packets solved the problem.
MS Link: http://support.microsoft.com/kb/941145
Thank you to everyone who tried to help and especially to David Heffernan who alluded to the possibility that something else was waking up the PC.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With