admin 管理员组文章数量: 887007
windows系统睡眠与合上盖子事件捕获
一、系统睡眠
1.1 睡眠事件
- PBT_APMSUSPEND 事件
通知应用程序计算机即将进入挂起状态。该事件通常在所有应用程序和可安装驱动程序返回TRUE给之前的PBT_APMQUERYSUSPEND 事件时传播。
窗口通过WM_POWERBROADCAST消息接收这个事件。wParam和lParam参数的设置如下所示。
LRESULT
CALLBACK
WindowProc( HWND hwnd, // handle to windowUINT uMsg, // WM_POWERBROADCASTWPARAM wParam, // PBT_APMSUSPENDLPARAM lParam); // zero
应用程序应该通过完成保存数据所需的所有任务来处理此事件。
系统允许应用程序大约两秒钟来处理此通知。过期后,如果应用仍在运行,可能会导致应用中断。
1.2 注册函数
- PowerRegisterSuspendResumeNotification 注册(一个函数)来接受系统挂起或者恢复时的通知
DWORD PowerRegisterSuspendResumeNotification([in] DWORD Flags,[in] HANDLE Recipient,[out] PHPOWERNOTIFY RegistrationHandle
);
Parameters
[in] Flags
这个参数必须是 DEVICE_NOTIFY_CALLBACK.
[in] Recipient
这个参数是指向DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS结构的指针。在本例中,回调函数是DeviceNotifyCallbackRoutine。 当Callback函数执行时,将设置Type参数,指示所发生事件的类型。 可能的值包括PBT_APMSUSPEND, PBT_APMRESUMESUSPEND, PBT_APMRESUMEAUTOMATIC。
typedef struct _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS {PDEVICE_NOTIFY_CALLBACK_ROUTINE Callback;//指示应用程序接收到通知时将调用的回调函数。 PVOID Context;//注册通知的应用程序的上下文。
} DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS, *PDEVICE_NOTIFY_SUBSCRIBE_PARAMETERS;DEVICE_NOTIFY_CALLBACK_ROUTINE DeviceNotifyCallbackRoutine;
ULONG DeviceNotifyCallbackRoutine(PVOID Context,ULONG Type,PVOID Setting
)
{...}
[out] RegistrationHandle
注册的返回的句柄,使用这个句柄来反注册以取消接受通知。
Return value
如果调用成功,返回ERROR_SUCCESS(零),如果调用失败,返回一个非零值。
- RegisterSuspendResumeNotification 注册以便在系统暂停或恢复时接收通知。类似于PowerRegisterSuspendResumeNotification,但在用户模式下操作,可以接受一个窗口句柄
HPOWERNOTIFY RegisterSuspendResumeNotification([in] HANDLE hRecipient,[in] DWORD Flags
);
Parameters
[in] hRecipient
此参数包含订阅电源通知或表示订阅过程的窗口句柄的参数。
如果Flags是DEVICE_NOTIFY_CALLBACK, hRecipient被解释为指向DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS结构体的指针。 在本例中,回调函数是DeviceNotifyCallbackRoutine。 当Callback函数执行时,将设置Type参数,指示所发生事件的类型。 可能的值包括PBT_APMSUSPEND, PBT_APMRESUMESUSPEND, PBT_APMRESUMEAUTOMATIC。
如果Flags是DEVICE_NOTIFY_WINDOW_HANDLE,则hreceiver是要传递事件的窗口句柄。
[in] Flags
这个参数可以是DEVICE_NOTIFY_WINDOW_HANDLE或者DEVICE_NOTIFY_CALLBACK。
Return value
注册的句柄。使用此句柄注销通知。
如果函数失败,返回值为NULL。要获得扩展的错误信息,请调用GetLastError。
1.3 PowerRegisterSuspendResumeNotification 示例
void ReigsterSleepNotify(std::function<void (int)> cb) {DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS dnsp{ [](PVOID Context, ULONG Type, PVOID Setting) noexcept -> ULONG {std::function<void(int)>* pCB = reinterpret_cast<std::function<void(int)>*>(Context);if (Type == PBT_APMSUSPEND) {std::cout << "PBT_APMSUSPEND" << std::endl;if (pCB) {(*pCB)(1);}}else if (Type == PBT_APMRESUMESUSPEND) {std::cout << "PBT_APMRESUMESUSPEND" << std::endl;if (pCB) {(*pCB)(0);}}else if (Type == PBT_APMRESUMEAUTOMATIC) {std::cout << "PBT_APMRESUMEAUTOMATIC" << std::endl;}else {std::cout << "Event type:" << Type << std::endl;}return TRUE;},&cb };HPOWERNOTIFY pRhBak;PowerRegisterSuspendResumeNotification(DEVICE_NOTIFY_CALLBACK, &dnsp, &pRhBak);
}
二、合上盖子
2.1 GUI 程序
- RegisterPowerSettingNotification
HPOWERNOTIFY RegisterPowerSettingNotification([in] HANDLE hRecipient,[in] LPCGUID PowerSettingGuid,[in] DWORD Flags
);
- 示例
#include <iostream>
#include <Windows.h>
#include <tchar.h>
#include <winnt.h>
#include <sstream>
#include <powrprof.h>
#include <powerbase.h>#pragma comment(lib,"Powrprof.lib")static long FAR PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{if (message == WM_POWERBROADCAST){std::cout << "WM_POWERBROADCAST" << std::endl;DWORD dwWParam = (DWORD)wParam;if (dwWParam == PBT_POWERSETTINGCHANGE) {//std::cout << "PBT_POWERSETTINGCHANGE" << std::endl;PPOWERBROADCAST_SETTING dwLParam = (PPOWERBROADCAST_SETTING)lParam;if (dwLParam->PowerSetting == GUID_LIDSWITCH_STATE_CHANGE) {//std::cout << "GUID_LIDSWITCH_STATE_CHANGE." << std::endl;if ((char)dwLParam->Data == '0') {std::cout << "lid close" << std::endl;}else if ((char)dwLParam->Data == '\x1') {std::cout << "lid open" << std::endl;}else {std::cout << "no lid open neither close" << std::endl;}}}return TRUE;}elsereturn DefWindowProc(hWnd, message, wParam, lParam);
}int main()
{std::cout << "Hello World!\n";MSG msg;BOOL bRet = FALSE;HWND hwnd = GetWindowHwndByPID(dsPID);NDCLASS wc = { 0 };// Set up and register window classwc.lpfnWndProc = WindowProc;wc.lpszClassName = _T("SomeNameYouInvented");RegisterClass(&wc);HWND hWin = CreateWindow(_T("SomeNameYouInvented"), _T(""), 0, 0, 0, 0, 0, NULL, NULL, NULL, 0);RegisterPowerSettingNotification(hWin, &GUID_LIDSWITCH_STATE_CHANGE, DEVICE_NOTIFY_WINDOW_HANDLE);//RegisterSuspendResumeNotification(hWin, DEVICE_NOTIFY_WINDOW_HANDLE);while ((bRet = GetMessage(&msg, hWin, 0, 0)) != 0){if (bRet == -1){// handle the error and possibly exit}else{TranslateMessage(&msg);DispatchMessage(&msg);}} Sleep(1000000);
}
2.2 非GUI程序
- 服务示例
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#include "sample.h"#pragma comment(lib, "advapi32.lib")#define SVCNAME TEXT("SvcName")SERVICE_STATUS gSvcStatus;
SERVICE_STATUS_HANDLE gSvcStatusHandle;
HANDLE ghSvcStopEvent = NULL;VOID SvcInstall(void);
VOID WINAPI SvcCtrlHandler( DWORD );
VOID WINAPI SvcMain( DWORD, LPTSTR * ); VOID ReportSvcStatus( DWORD, DWORD, DWORD );
VOID SvcInit( DWORD, LPTSTR * );
VOID SvcReportEvent( LPTSTR );//
// Purpose:
// Entry point for the process
//
// Parameters:
// None
//
// Return value:
// None, defaults to 0 (zero)
//
int __cdecl _tmain(int argc, TCHAR *argv[])
{ // If command-line parameter is "install", install the service. // Otherwise, the service is probably being started by the SCM.if( lstrcmpi( argv[1], TEXT("install")) == 0 ){SvcInstall();return 0;}// TO_DO: Add any additional services for the process to this table.SERVICE_TABLE_ENTRY DispatchTable[] = { { SVCNAME, (LPSERVICE_MAIN_FUNCTION) SvcMain }, { NULL, NULL } }; // This call returns when the service has stopped. // The process should simply terminate when the call returns.if (!StartServiceCtrlDispatcher( DispatchTable )) { SvcReportEvent(TEXT("StartServiceCtrlDispatcher")); }
} //
// Purpose:
// Installs a service in the SCM database
//
// Parameters:
// None
//
// Return value:
// None
//
VOID SvcInstall()
{SC_HANDLE schSCManager;SC_HANDLE schService;TCHAR szUnquotedPath[MAX_PATH];if( !GetModuleFileName( NULL, szUnquotedPath, MAX_PATH ) ){printf("Cannot install service (%d)\n", GetLastError());return;}// In case the path contains a space, it must be quoted so that// it is correctly interpreted. For example,// "d:\my share\myservice.exe" should be specified as// ""d:\my share\myservice.exe"".TCHAR szPath[MAX_PATH];StringCbPrintf(szPath, MAX_PATH, TEXT("\"%s\""), szUnquotedPath);// Get a handle to the SCM database. schSCManager = OpenSCManager( NULL, // local computerNULL, // ServicesActive database SC_MANAGER_ALL_ACCESS); // full access rights if (NULL == schSCManager) {printf("OpenSCManager failed (%d)\n", GetLastError());return;}// Create the serviceschService = CreateService( schSCManager, // SCM database SVCNAME, // name of service SVCNAME, // service name to display SERVICE_ALL_ACCESS, // desired access SERVICE_WIN32_OWN_PROCESS, // service type SERVICE_DEMAND_START, // start type SERVICE_ERROR_NORMAL, // error control type szPath, // path to service's binary NULL, // no load ordering group NULL, // no tag identifier NULL, // no dependencies NULL, // LocalSystem account NULL); // no password if (schService == NULL) {printf("CreateService failed (%d)\n", GetLastError()); CloseServiceHandle(schSCManager);return;}else printf("Service installed successfully\n"); CloseServiceHandle(schService); CloseServiceHandle(schSCManager);
}//
// Purpose:
// Entry point for the service
//
// Parameters:
// dwArgc - Number of arguments in the lpszArgv array
// lpszArgv - Array of strings. The first string is the name of
// the service and subsequent strings are passed by the process
// that called the StartService function to start the service.
//
// Return value:
// None.
//
VOID WINAPI SvcMain( DWORD dwArgc, LPTSTR *lpszArgv )
{// Register the handler function for the servicegSvcStatusHandle = RegisterServiceCtrlHandler( SVCNAME, SvcCtrlHandler);if( !gSvcStatusHandle ){ SvcReportEvent(TEXT("RegisterServiceCtrlHandler")); return; } // These SERVICE_STATUS members remain as set heregSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; gSvcStatus.dwServiceSpecificExitCode = 0; // Report initial status to the SCMReportSvcStatus( SERVICE_START_PENDING, NO_ERROR, 3000 );// Perform service-specific initialization and work.SvcInit( dwArgc, lpszArgv );
}//
// Purpose:
// The service code
//
// Parameters:
// dwArgc - Number of arguments in the lpszArgv array
// lpszArgv - Array of strings. The first string is the name of
// the service and subsequent strings are passed by the process
// that called the StartService function to start the service.
//
// Return value:
// None
//
VOID SvcInit( DWORD dwArgc, LPTSTR *lpszArgv)
{// TO_DO: Declare and set any required variables.// Be sure to periodically call ReportSvcStatus() with // SERVICE_START_PENDING. If initialization fails, call// ReportSvcStatus with SERVICE_STOPPED.// Create an event. The control handler function, SvcCtrlHandler,// signals this event when it receives the stop control code.ghSvcStopEvent = CreateEvent(NULL, // default security attributesTRUE, // manual reset eventFALSE, // not signaledNULL); // no nameif ( ghSvcStopEvent == NULL){ReportSvcStatus( SERVICE_STOPPED, GetLastError(), 0 );return;}// Report running status when initialization is complete.ReportSvcStatus( SERVICE_RUNNING, NO_ERROR, 0 );// TO_DO: Perform work until service stops.while(1){// Check whether to stop the service.WaitForSingleObject(ghSvcStopEvent, INFINITE);ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );return;}
}//
// Purpose:
// Sets the current service status and reports it to the SCM.
//
// Parameters:
// dwCurrentState - The current state (see SERVICE_STATUS)
// dwWin32ExitCode - The system error code
// dwWaitHint - Estimated time for pending operation,
// in milliseconds
//
// Return value:
// None
//
VOID ReportSvcStatus( DWORD dwCurrentState,DWORD dwWin32ExitCode,DWORD dwWaitHint)
{static DWORD dwCheckPoint = 1;// Fill in the SERVICE_STATUS structure.gSvcStatus.dwCurrentState = dwCurrentState;gSvcStatus.dwWin32ExitCode = dwWin32ExitCode;gSvcStatus.dwWaitHint = dwWaitHint;if (dwCurrentState == SERVICE_START_PENDING)gSvcStatus.dwControlsAccepted = 0;else gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;if ( (dwCurrentState == SERVICE_RUNNING) ||(dwCurrentState == SERVICE_STOPPED) )gSvcStatus.dwCheckPoint = 0;else gSvcStatus.dwCheckPoint = dwCheckPoint++;// Report the status of the service to the SCM.SetServiceStatus( gSvcStatusHandle, &gSvcStatus );
}//
// Purpose:
// Called by SCM whenever a control code is sent to the service
// using the ControlService function.
//
// Parameters:
// dwCtrl - control code
//
// Return value:
// None
//
VOID WINAPI SvcCtrlHandler( DWORD dwCtrl )
{// Handle the requested control code. switch(dwCtrl) { case SERVICE_CONTROL_STOP: ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);// Signal the service to stop.SetEvent(ghSvcStopEvent);ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);return;case SERVICE_CONTROL_INTERROGATE: break; default: break;} }//
// Purpose:
// Logs messages to the event log
//
// Parameters:
// szFunction - name of function that failed
//
// Return value:
// None
//
// Remarks:
// The service must have an entry in the Application event log.
//
VOID SvcReportEvent(LPTSTR szFunction)
{ HANDLE hEventSource;LPCTSTR lpszStrings[2];TCHAR Buffer[80];hEventSource = RegisterEventSource(NULL, SVCNAME);if( NULL != hEventSource ){StringCchPrintf(Buffer, 80, TEXT("%s failed with %d"), szFunction, GetLastError());lpszStrings[0] = SVCNAME;lpszStrings[1] = Buffer;ReportEvent(hEventSource, // event log handleEVENTLOG_ERROR_TYPE, // event type0, // event categorySVC_ERROR, // event identifierNULL, // no security identifier2, // size of lpszStrings array0, // no binary datalpszStrings, // array of stringsNULL); // no binary dataDeregisterEventSource(hEventSource);}
}
- RegisterServiceCtrlHandlerExA
SERVICE_STATUS_HANDLE RegisterServiceCtrlHandlerExA([in] LPCSTR lpServiceName,[in] LPHANDLER_FUNCTION_EX lpHandlerProc,[in, optional] LPVOID lpContext
);LPHANDLER_FUNCTION_EX LphandlerFunctionEx;DWORD LphandlerFunctionEx([in] DWORD dwControl,[in] DWORD dwEventType,[in] LPVOID lpEventData,[in] LPVOID lpContext
)
{...}
[in] dwControl
控制代码。如SERVICE_CONTROL_POWEREVENT。
[in] dwEventType
如果dwControl是SERVICE_CONTROL_POWEREVENT,这个参数可以是WM_POWERBROADCAST消息的wParam参数中指定的值之一。见下面的PBT_POWERSETTINGCHANGE事件。
-
SERVICE_CONTROL_POWEREVENT事件
SERVICE_CONTROL_POWEREVENT 0x0000000D 通知服务系统电源事件。dwEventType参数包含其他信息。如果dwEventType是PBT_POWERSETTINGCHANGE, lpEventData参数还包含额外的信息。 -
PBT_POWERSETTINGCHANGE事件
LRESULT
CALLBACK
WindowProc( HWND hwnd, // handle to windowUINT uMsg, // WM_POWERBROADCASTWPARAM wParam, // PBT_POWERSETTINGCHANGELPARAM lParam); // Pointer to POWERBROADCAST_SETTING
typedef struct {GUID PowerSetting;DWORD DataLength;UCHAR Data[1];
} POWERBROADCAST_SETTING, *PPOWERBROADCAST_SETTING;
本文标签: windows系统睡眠与合上盖子事件捕获
版权声明:本文标题:windows系统睡眠与合上盖子事件捕获 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1732355887h1534425.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论