何ができるの原因ウunhook低レベル(グローバルキーボードフック?
-
27-09-2019 - |
質問
またグローバルキーボードフックの設置によ SetWindowsHookEx
と WH_KEYBOARD_LL
登場するランダムに得unhookedます。
していることを確認しました彼らはフックが付けで呼び出し UnhookWindowsHookEx
の対応を返します false
.もることの確認を返します true
でした。)
あるという一貫したリプロと言っていることとなっているがunhookedによりタイムアウトまたは例外なくなっちゃうがたっても直らせで座ってブレークポイントの取り扱い方法に渡る分、どんなふうにランダム例外(C#)でも表示されます。
当社のコールバックした後に別のスレッドでしょうか。っくりとしたソリューションがWindows7の設定のタイムアウト上のレジストリでのWindows7ではより積極的にタイムアウトでう(いしていますが、Win7でにここにいることができない場合その他のOSがないような理想的なソリューション.
私は考えず、背景のスレッドをリフレッシュフックの中には、はhackishがわからないの本当のマイナスの影響をもたらすことでより変化するグローバルはWindowsのレジストリ設定あり。
その他のご提案ソリューション? 両方のクラスを設定するフックの代表着している静的なすべきではないっGCい.
編集:検証への呼び出し GC.Collect();
ないものも少なくなってきている最善を収集します。
解決
これはタイムアウトの問題でなければならないと思います。
他の開発者は、(文書化されていない)タイムアウト値を超えた場合、低レベルのフックが外れているWindows7固有の問題を報告しています。
見る このスレッド 同じ問題について議論する他の開発者のために。睡眠をとるのではなく、忙しいループ(または遅いゴミコレクション)を実行する必要があるかもしれません。 LowLevelKeyBoardProc関数のブレークポイントもタイムアウトの問題を引き起こす可能性があります。 (別のタスクによる重いCPU負荷が動作を引き起こす可能性があるという観察もあります。おそらく、他のタスクがCPUサイクルをLowLevelKeyBoardProc関数から盗み、それが時間がかかりすぎるためです。)
そのスレッドで提案されている解決策は、 LowLevelHookstimeout レジストリのDWORD値 hkey_current_user controlパネルデスクトップ より大きな値に。
C#の栄光の1つは、ごみ収集が発生した場合、単純なステートメントでさえも膨大な時間がかかる可能性があることを忘れないでください。
他のヒント
あるもののあり方を考えることができる場所は問題です。
めの分離の問題の位置、他
WH_KEYBOARD_LL
フックと同時に現在のフックというもの以外のデータをフックする。きるオリジナルのフックはunhooked,いてはこちらをご確認くださいもしこの"ダミー"フックもunhooked.の場合にダミーフックもunhookedできるのか特定の問題は外部のフック(Windowsにはも"ことば"に関連するプロセスかどうかはわかりません。) の場合にダミーフックませんでしたunhooked、その問題はどこか内のフック。ログ情報を貴社のフックにコールバック関数を実行までのフックがunhooked.これを繰り返し回数のログデータをできるかどうかを見極パターンのunhooking.
私はこれを一時だけでなく、どちらにも影響を及ぼす他者の結果となります。場していないが、問題の役割を果たすことができるのだろ走行されていったといわれている。
それはロングショットですが、たまたまアンチウイルスソフトウェアを実行していますか?それはキーボードフックに気づき、それをキックアウトすることが非常によくあります。
それはあなたに警告し、すぐにそれを削除する可能性が高いですが、それはチェックする価値のある奇妙なことの1つです。
おそらく、他の誰かがCallNextoKex()を呼び出していないフックを持っていますか?
私はそれが醜いソリューションであることを知っていますが、あなたは永遠に5分間タイマーを設定することができます、そしてあなたはあなたのキーボードイベントを再ホックすることができますか?
私はWin7マシンで同じ問題を抱えていましたが、しばらくするとキーボードフックがリファレンスを失い、5分ごとにイベントを再びフックするためにタイマーを設定する必要がありました。
次のプロジェクトを使用しています。 http://www.codeproject.com/articles/7294/processing-global-mouse-and-keyboard-fooks-in-c 特定のキーが押されたときにタスクを実行します。
ホットキーでタスクを実行した後、新しいキープレスを聞くのをやめた後、keyboardhooklistenerを静的に変更し、問題を解決するように見えました。なぜこれが私の問題を解決したのかわからないので、これについてお気軽にコメントしてください!
私のホットキークラス:
class Hotkey
{
private static KeyboardHookListener _keyboardHookListener;
public void Start()
{
_keyboardHookListener = new KeyboardHookListener(new GlobalHooker()) { Enabled = true };
_keyboardHookListener.KeyDown += KeyboardListener_OnkeyPress;
}
private void KeyboardListener_OnkeyPress(object sender, KeyEventArgs e)
{
// Let's backup all projects
if (e.KeyCode == Keys.F1)
{
// Initialize files
var files = new Files();
// Backup all projects
files.BackupAllProjects();
}
// Quick backup - one project
else if (e.KeyCode == Keys.F2)
{
var quickBackupForm = new QuickBackup();
quickBackupForm.Show();
}
}
}
非常に遅いですが、私は何かを共有していると思いました。から集まる ここ SetWindowshookexを別のスレッドに置くなど、いくつかのヒントがあり、それがよりスケジューリングの問題であることがあります。
また、application.doeventsがかなりのCPUを使用していることに気付き、Peekmessageの使用量が少ないことがわかりました。
public static bool active = true;
[StructLayout(LayoutKind.Sequential)]
public struct NativeMessage
{
public IntPtr handle;
public uint msg;
public IntPtr wParam;
public IntPtr lParam;
public uint time;
public System.Drawing.Point p;
}
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool PeekMessage(out NativeMessage message,
IntPtr handle, uint filterMin, uint filterMax, uint flags);
public const int PM_NOREMOVE = 0;
public const int PM_REMOVE = 0x0001;
protected void MouseHooker()
{
NativeMessage msg;
using (Process curProcess = Process.GetCurrentProcess())
{
using (ProcessModule curModule = curProcess.MainModule)
{
// Install the low level mouse hook that will put events into _mouseEvents
_hookproc = MouseHookCallback;
_hookId = User32.SetWindowsHookEx(WH.WH_MOUSE_LL, _hookproc, Kernel32.GetModuleHandle(curModule.ModuleName), 0);
}
}
while (active)
{
while (PeekMessage(out msg, IntPtr.Zero,
(uint)WM.WM_MOUSEFIRST, (uint)WM.WM_MOUSELAST, PM_NOREMOVE))
;
Thread.Sleep(10);
}
User32.UnhookWindowsHookEx(_hookId);
_hookId = IntPtr.Zero;
}
public void HookMouse()
{
active = true;
if (_hookId == IntPtr.Zero)
{
_mouseHookThread = new Thread(MouseHooker);
_mouseHookThread.IsBackground = true;
_mouseHookThread.Priority = ThreadPriority.Highest;
_mouseHookThread.Start();
}
}
したがって、アクティブなイベントでアクティブなブールをFalseに変更し、アクティブ化されたイベントでFookMouseに電話してください。
Hth
編集:私はこれでゲームが減速していることに気づいたので、アクティブ化されたイベントを使用してアプリがアクティブでない場合に外すことにしました。