i have headless computer running custom service want enable/disable using power button, rather having remotely connect every time. computer other things well, turning off not option.
is possible hook system power button under windows xp & up, such program event before windows initiates powerdown/sleep event (before pbt_apmquerysuspend
event sent out)?
this indeed possible, it's bit hackish , requires 2 different implementations depending on windows version. both methods, need set power button put computer sleep in power options.
windows xp , below:
you need overwrite program's main window's wndproc
function. on ides don't support natively, can done using setwindowlong
in user32 api. in custom wndproc
function, listen wm_powerbroadcast (0x218)
message. if receive message wparam of pbt_apmquerysuspend (0x0)
, call wanted function , return broadcast_query_deny (0x424d5144)
instead of calling base wndproc
function. example code:
//at program start //gwl_wndproc = -4 oldwndproc = setwindowlong(this.hwnd, gwl_wndproc, &mywndproc) //in mywndproc(hwnd, wmsg, wparam, lparam) //wm_powerbroadcast = 0x218 //pbt_apmquerysuspend = 0x0 //broadcast_query_deny = 0x424d5144 if wmsg = wm_powerbroadcast && wparam = pbt_apmquerysuspend ( //call function here! return broadcast_query_deny ) return callwindowproc(oldwndproc, hwnd, wmsg, wparam, lparam) //before exiting setwindowlong(me.hwnd, gwl_wndproc, oldwndproc)
windows vista & up: (thanks remy lebeau setting me on right track)
you need override wndproc
xp, call setthreadexecutionstate
in kernel32 api disable sleep mode , registerpowersettingnotification
in user32 api listen advanced power notifications. listening, in particular, guid_system_awaymode
notification, gets sent out when system asked go sleep unable so. convert string formed lpcguid
can use uuidfromstringa
in rpcrt4.dll api. example code:
typedef struct uuid{ int d1, d2, d3, d4 } lpcguid; //at program start //gwl_wndproc = -4 //es_continuous = 0x80000000 //es_system_required = 0x1 //es_awaymode_required = 0x40 //guid_system_awaymode = "98a7f580-01f7-48aa-9c0f-44352c29e5c0" lpcguid uid; oldwndproc = setwindowlong(this.hwnd, gwl_wndproc, &mywndproc) setthreadexecutionstate(es_continuous | es_system_required | es_awaymode_required) uuidfromstringa(*(guid_system_awaymode), uid) ps = registerpowersettingnotification(this.hwnd, uid, 0) //in mywndproc(hwnd, wmsg, wparam, lparam) //wm_powerbroadcast = 0x218 //pbt_powersettingchange = 0x8013 if wmsg = wm_powerbroadcast && wparam = pbt_powersettingchange ( //call function here! //you can additionally extract data lparam verify //this notification you're waiting (see below) ) return callwindowproc(oldwndproc, hwnd, wmsg, wparam, lparam) //before exiting setwindowlong(me.hwnd, gwl_wndproc, oldwndproc) unregisterpowersettingnotification(ps)
this method has side effect of turning off physical screen (not problem on headless machine), , possibly locking session. make sure disable prompting password after sleeping avoid this. there's additional useful information on registerpowersettingnotification
available here shows how extract information lparam
in wndproc
function in case want additional info on notification. have fun ;)