可等待定時器(獲取系統時間)
可等待定時器這種內核對象,它們會在某個指定的時間觸發,或每隔一段時間觸發一次。它們通常用來在某個時間執行一些操作。
0x01 創建一個可等待定時器 CreateWaitableTimer
(在創建的時候,可等待的計時器對象總是處於未觸發狀態)
HANDLE WINAPI CreateWaitableTimer(
__in_opt LPSECURITY_ATTRIBUTES lpTimerAttributes, //安全描述符,為NULL時使用默認的
__in BOOL bManualReset, //要創建一個手動重置定時器還是一個自動重置計時器
//當手動重置
//當自動重置計時器被觸發時,只有一個正在等待該計時的線程會變成可調度狀態
__in_opt LPCTSTR lpTimerName //該可等待計時器的名稱
);
0x02 獲取一個已經存在的可等待計時器的句柄 OpenWaitableTimer
HANDLE WINAPI OpenWaitableTimer(
__in DWORD dwDesiredAccess, //訪問權限
__in BOOL bInheritHandle, //是否允許子進程繼承該句柄
__in LPCTSTR lpTimerName //要打開的對象名稱
);
0x03 觸發計時器 SetWaitableTimer函數
BOOL WINAPI SetWaitableTimer(
__in HANDLE hTimer, //想要觸發的計時器
__in const LARGE_INTEGER *pDueTime, //計時器第一次觸發的時間
__in LONG lPeriod, //第一次觸發後,計時器的觸發頻度,當給lPeriod參數傳0時,我們設置的是一次性定時器,這種定時器只觸發一次,之後再不觸發。
__in_opt PTIMERAPCROUTINE pfnCompletionRoutine, //異步過程調用APC函數
__in_opt LPVOID lpArgToCompletionRoutine, //APC函數的參數
__in BOOL fResume //是否繼續執行,一般傳FALSE
);
0x04 將指定的計時器取消 CancelWaitableTimer函數
BOOL WINAPI CancelWaitableTimer(
__in HANDLE hTimer
);
這樣計時器就永遠不會觸發了,除非以後再調用SetWaitableTimer來對它進行重置。如果想要改變觸發器的觸發時間,不必先調用CancelWaitableTimer,因為每次調用SetWaitableTimer都會在設置新的觸發時間之前將原來的觸發時間取消掉。
// 計時器.cpp : 定義控制臺應用程序的入口點。 // #include "stdafx.h" #include <windows.h> #include <iostream> #include <ctime> using namespace std; DWORD WINAPI ThreadProcedure(LPVOID ParameterData); void GetSystemTime(); BOOL __IsLoop = TRUE; int main() { HANDLE ThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProcedure, NULL, 0, NULL); printf("Input AnyKey To Exit\r\n"); getchar(); __IsLoop = FALSE; WaitForSingleObject(ThreadHandle, INFINITE); if (ThreadHandle!=NULL) { CloseHandle(ThreadHandle); ThreadHandle = NULL; } return 0; } DWORD WINAPI ThreadProcedure(LPVOID ParameterData) { //創建一個時鐘 HANDLE TimeHandle = NULL; LARGE_INTEGER DueTime; DueTime.QuadPart = -10000000; TimeHandle = CreateWaitableTimer(NULL, FALSE, NULL); //同步事件(SynchronizationEvent) //當事件對象為激發時,如遇到KeWaitForXX等內核函數,事件對象則自動變回未激發態 //通知事件(NotificationEvent) //當事件對象為激發時,如遇到KeWaitForXX等內核函數,事件對象則不會變回未激發態 //If this parameter is TRUE, the timer is a manual-reset notification timer. Otherwise, the timer is a synchronization timer. while (__IsLoop) { if (!SetWaitableTimer(TimeHandle, &DueTime, 0, NULL, NULL, 0)) { printf("SetWaitableTimer failed (%d)\n", GetLastError()); return 0; } BOOL IsOk = WaitForSingleObject(TimeHandle, INFINITE); IsOk -= WAIT_OBJECT_0; if (IsOk==0) { system("cls"); GetSystemTime(); } else { break; } } CancelWaitableTimer(TimeHandle); CloseHandle(TimeHandle); TimeHandle = NULL; printf("ThreadProcedure() Exit\r\n"); return 0; } void GetSystemTime() { char TimeData[MAX_PATH] = { 0 }; auto TimeObject = time(NULL); tm v1; localtime_s(&v1, &TimeObject); //格式化時間字符串 strftime(TimeData, _countof(TimeData), "%Y-%m-%d %H:%M:%S", &v1); printf("%s\r\n", TimeData); }
可等待定時器(獲取系統時間)