![](/img/trans.png)
[英]Some windows in Windows 8 prevent my low-level keyboard hook from working
[英]Is it possible to detect when a low-level keyboard hook has been automatically disconnected by Windows?
我正在開發一個使用鍵盤掛鈎的程序。 但是,當運行程序的 PC 只是稍微過載時,它會導致 Windows 將掛鈎與程序斷開,導致它不再響應擊鍵。
有沒有辦法通過使用不同的架構(可能涉及管道)來防止這種情況,或者甚至更好地提出解決完全相同問題的不同方法?
您無法“檢測”到這一點,而且您絕對不需要。 您所描述的是一項功能,特別是 Windows 7 中引入的一項功能,用於保護您的系統免受惡意應用程序的侵害。
因此,適用的文檔對其進行了描述(特別注意粗體部分):
掛鈎過程應在比以下注冊表項中的
LowLevelHooksTimeout
值中指定的數據條目更短的時間內處理消息:HKEY_CURRENT_USER\Control Panel\Desktop
該值以毫秒為單位。 如果鈎子過程超時,系統將消息傳遞給下一個鈎子。 但是,在 Windows 7 及更高版本上,掛鈎會在不被調用的情況下被靜默刪除。 應用程序無法知道掛鈎是否被移除。
這里的解決方案肯定不是想出一種方法來“檢測”鈎子何時被卸載並重新安裝。 當操作系統第一次卸載鈎子時,您應該已經發現自己做錯了。
實際的解決方案是重新設計您的應用程序以更快地從掛鈎過程中返回。 理想情況下,您應該幾乎立即返回。 如果您需要運行某種類型的密集計算以響應低級消息(我無法想象您為什么會這樣做),那么您應該存儲您收到的信息,從掛鈎過程返回,然后在稍后(可能在單獨的線程上)。
事實上,這幾乎正是文檔繼續建議的內容:
注意:調試掛鈎無法跟蹤此類低級鍵盤掛鈎。 如果應用程序必須使用低級掛鈎,它應該在專用線程上運行掛鈎,將工作傳遞給工作線程,然后立即返回。 在應用程序需要使用低級掛鈎的大多數情況下,它應該監視原始輸入。 這是因為原始輸入可以比低級掛鈎更有效地異步監視針對其他線程的鼠標和鍵盤消息。 有關原始輸入的更多信息,請參閱原始輸入。
我不太確定鍵盤掛鈎總是受到指責。 我們似乎都同意,在理想或平均條件下,一切都應該響應。 但是在從啟動到關閉的整個生命周期中,鈎子還必須在一些最壞的情況下生存下來。 在我的公司,我們編寫了一些鍵盤鈎子,它們盡可能輕量級和異步,但它們仍然偶爾會出現斷開連接。
作為用戶,我每天要輸入數萬個字符。 我最多每月重啟一次,有時我會因為跳過 Windows 更新而感到內疚。 有了暫停和 hibernate 等選項,我認為我並不孤單。 作為開發人員,我必須確保鈎子從頭到尾一直運行,無論系統發生什么。
通常我的系統反應靈敏。 但是可能會有短暫的、特殊的時刻,它會跪下,甚至 Windows Aero 也會被關閉。 現在它非常活潑。 但是如果我按下 Show Desktop 按鈕,在我的 65 左右打開的 windows 全部折疊期間,鼠標將凍結至少一秒鍾。 如果我在其中一個時刻按下一個鍵怎么辦?
如果 Windows 可以凍結鼠標一秒鍾,如果 Windows 甚至可以在短暫的重載時刻關閉 Aero,為什么不能讓鍵盤鈎子在類似的異常過載時間內存活? 相反,因為一個特殊的時刻,Windows 拔掉了插頭,默默地影響了剩余的計算體驗,直到系統關閉。 在 200 毫秒內僅影響我們每天按下的數千次按鍵中的一個按鍵,就在那幾分之一秒內,我,用戶,必須重新啟動系統,因為這是我理解的唯一方法,它將帶回鍵盤宏或任何實用程序我依靠我的富有成效的工作。
即使保證可以防止上述情況(最壞情況的經驗似乎表明並非如此),我也不確定所有事情都可以在單獨的線程中輕松完成。 例如,假設用戶設置了一個熱鍵來啟動應用程序。 難道不能有從當前上下文(前台 window、權限等)啟動應用程序的理由嗎? 用戶實際期望並接受延遲難道不是合理的嗎,因為他知道,使用鍵盤,他只是開始了一些需要更長時間的事情? 我不知道這個例子在技術上是否合理,但我想說明有時由於已知事件而可能無法接受的事情是如何被接受的。
鍵盤掛鈎對很多事情都非常有用,從宏到糾錯再到啟動事物,Windows 7 中引入的這種行為將好與壞、可接受和不可接受、平均和例外放在一起籃子。 這傷害了用戶和開發人員,因為高質量的鍵盤鈎子可能會被殺死。 想象一下,當您的應用程序在正常條件下運行良好時沒有官方解決方案,但在某些重負載(或其他莫名其妙的)情況下被隨機殺死,這是一場多么可怕的噩夢。
用一個問題來結束這個問題,有誰知道 Windows 8 下的狀態是什么,有什么變化嗎?
Cody Gray 的響應非常好,但是 FWIW,純粹出於測試目的,您可能能夠檢測到斷開的掛鈎。
當你的鈎子進程被調用時,將當前的滴答計數存儲在一個可供主線程訪問的變量中。 在主線程中,定期調用GetLastInputInfo
。 它將為您提供系統中最后一個輸入事件的滴答計數(不僅僅是在您的進程中)。 如果GetLastInputInfo
提供的值明顯晚於(更新)您的最后一個鈎子 proc 滴答計數,則可以很好地猜測鈎子已斷開連接。
嘗試提高申請流程的優先級。
我認為您的鈎子中有一些“性能不佳”的代碼。 這就是為什么會稍微超載的原因。
“它會導致 Windows 斷開掛鈎與程序的連接”
您的鈎子中是否出現任何錯誤並且您不處理它?
AFAIK,Windows 如果它本身運行良好,就不會斷開掛鈎。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.