關 閉

        新聞中心

        EEPW首頁 > 工控自動化 > 設計應用 > 監視、控制計算機的使用

        監視、控制計算機的使用

        作者: 時間:2012-08-17 來源:網絡 收藏

        基于Windows NT/2000 的應用系統中,一些關鍵的人機交互工作站,常需要了解并記錄所有操作人員操作的情況。

        本文引用地址:http://www.104case.com/article/202220.htm

        如: 在工業控制領域,一些使用對設備進行和控制的工作站,需要非常高的可靠性和安全性。在這些工作站上通常要求只能運行系統所要求的應用程序,不能運行與系統無關的程序,同時要求對操作人員的所有原始輸入進行記錄,以便出現事故(如操作故障、程序異常退出)的時候,用來分析是人為原因,還是系統原因造成的。

        基于以上需求,我們必須解決兩個問題,一個是如何記錄操作人員的輸入,另一個是如何控制操作人員的輸入。在DOS、Windows 3.1、Windows 95/98中都可以編寫響應鍵盤和鼠標輸入的中斷處理程序,截取來自鍵盤和鼠標的輸入,記錄、分析后依情況分別處理。

        但是在Windows NT和 Windows 2000中,這樣的解決方法將不再行得通,這是因為Windows NT/2000操作系統為了提高系統的可靠性,不再允許應用程序直接對系統設備的底層進行操作。這樣,用戶的應用程序將不能夠對計算機的端口地址進行讀寫操作,所以在Windows NT/2000操作系統中對計算機端口的讀寫是無效的。

        另外一種方法能夠非常完美地解決這個問題,就是可以編寫操作系統的設備驅動程序來解決,但是要編寫系統的設備驅動程序,必須對Windows NT/2000的系統底層以及整個系統架構有比較深入的了解。而且設備驅動程序的編寫、調試都比較困難,同時這方面的資料也比較少。所以本文沒有采取這種方法,而是采用微軟公布的標準Win32 函數和鉤子技術來解決這個問題,比較方便而且快捷。

        在Windows NT/2000 操作系統中,稱各種輸入為事件(Event),所有的鍵盤、鼠標輸入事件以及其他事件都是通過消息傳遞處理機制來得到響應的。控制、計算機實際上是控制、事件消息流。Windows操作系統為這種應用提供鉤子(Hook)技術。這種技術的要點就是在操作系統的消息傳遞處理機制上外掛一個我們定義的函數,可以使用這個函數來監視、控制系統的事件消息流。本文采用的就是這種方法,這種方法要求將所有的程序代碼放入系統可以加載的動態鏈接庫中。

        下面我們以鍵盤輸入的監視和控制為例詳細敘述這種方法。其總體思路如下: 首先,定義自己的鉤子函數。 其次,安裝自定義的鉤子函數,此后鉤子函數在后臺開始工作。一旦系統發現擊鍵動作或者鼠標動作,系統將馬上調用該自定義的鉤子函數,并將事件消息傳入,供程序分析判斷。它可以監視所有的擊鍵和鼠標動作,與DOS 時代的中斷調用有非常相似的地方。最后,卸載自定義的鉤子函數。

        鉤子函數 的定義 微軟的鉤子技術的原理就是應用程序可以在系統的消息處理機制上外掛一個子程序,在消息尚未到達目的地之前,用該子程序來截獲此消息,以進行監視和控制。我們這里使用的是WH_KEYBOARD_LL類型的鉤子函數,這種類型的鉤子函數可以截獲所有的鍵盤事件,即敲擊鍵盤上的任何一個鍵,我們自定義的鉤子函數都可以知道。該類型鉤子函數要求安裝自定義的鉤子函數必須是以下原型:

        LRESULT CALLBACK LowLevelKeyboard- Proc( int nCode, WPARAM wParam, LPARAM lParam );

        其中各參數的含義如下: int nCode: 用來決定鉤子函數如何處理事件消息的代碼,參數的取值為HC_ACTION時,參數wParam、lParam包含了所需的鍵盤消息事件信息。

        WPARAM wParam: 鍵盤消息事件的類型ID。該參數有四種可能的消息類型取值:

        WM_KEY- DOWN,WM_KEYUP,WM_SYSKEYDOWN, WM_SYSKEYUP. LPARAM lParam:

        指向一個類型為KBDLLHOOKSTRUCT的結構指針。該結構容納了底層鍵盤輸入事件的詳細信息,它的定義如下: typedef struct tagKBDLLHOOKSTRUCT { DWORD vkCode; //一個范圍從1到254的虛擬鍵碼 DWORD scanCode; // 鍵盤的硬件掃描碼 DWORD flags; // 一系列的標志位 //0比特位指示該鍵是不是擴展鍵(如: 功能鍵,或數字小鍵盤上的鍵),1表示是,0表示否 //1~3比特位保留 //4比特位用來區分該事件是否來自Win32 函數keybd_event()調用,1表示是,0表示否 //5比特位為狀態描述碼,如果ALT鍵按下,該位是1,否則是0。 //6比特位保留。 //7比特位是變換狀態位,鍵被按下為0,鍵被釋放為1。

        DWORD time; // 該消息事件的時間標記。 DWORD dwExtraInfo; // 該消息的其他擴展信息。

        }KBDLLHOOKSTRUCT, FAR *LPKBDLLHOOK STRUCT, *PKBDLLHOOKSTRUCT;

        實際的鉤子函數的框架如下:

        LRESULT CALLBACK MyLowLevelKeyboard Proc(int nCode,

        WPARAM wParam,LPARAM lParam) { BOOL bSkipThisEvent = FALSE;

        HWND hwndForeground;

        HWND hwndFocus;

        DWORD dwCurrentThreadId;

        DWORD dwWindowThreadId;

        if (nCode == HC_ACTION) { PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)

        lParam; //系統傳遞來的鍵盤輸入事件信息指針

        switch (wParam) { case WM_SYSKEYUP: case WM_KEYUP: //if key up /*

        這段代碼用來獲得當前擁有輸入焦點的窗口的窗口句柄,以便獲得該窗口的相關信息*/ /*獲得前端窗口(即用戶當前正在工作的窗口)的句柄,創建該窗口的線程通常擁有比其他線程稍微高一些的優先級。

        */ hwndForegroud=::GetForegroundWindow(); dwCurrentThreadId=::GetCurrentThreadId(); //當前線程的Id //獲得產生前端窗口hwndForeground的線程Id值,用來惟一表示一個線程 dwWindowThreadId=::GetWindowThread- ProcessId(hwndForegroud,NULL); /*

        下面這一行代碼非常重要,它的作用是使當前線程(dwCurrentThreadId)的輸入處理機制依附到創建前端窗口的線程(dwWindowThreadId)的輸入機制上,否則你將得不到當前擁有鍵盤輸入焦點的窗口句柄。這是因為在Windows NT/2000操作系統通常創建不同的線程來處理相互獨立的輸入過程,每一個輸入過程都擁有自己的輸入狀態(焦點、鍵盤狀態、隊列狀態等),通過AttachThreadInput調用,操作系統將允許調用線程獲得或者設置其他線程生成窗口的輸入狀態信息。只有執行該系統調用,才能夠得到當前擁有鍵盤輸入焦點的窗口的窗口句柄,否則GetFocus()系統調用將返回NULL。


        上一頁 1 2 下一頁

        關鍵詞: 監視 計算機

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 唐海县| 托克托县| 嘉义市| 海盐县| 安国市| 健康| 博罗县| 宁化县| 从江县| 泰来县| 新密市| 保山市| 和顺县| 无锡市| 东山县| 湘乡市| 石门县| 桐梓县| 蓝山县| 耒阳市| 铜梁县| 郧西县| 龙游县| 江西省| 德安县| 阳城县| 吴旗县| 嵩明县| 聂荣县| 高密市| 万山特区| 湖北省| 鄂托克旗| 施秉县| 阿鲁科尔沁旗| 屯门区| 牡丹江市| 隆安县| 五家渠市| 青田县| 梁山县|