Крюк клавиатуры С# работает только 10 раз, а затем останавливается (или подавляется)?

Это классический низкоуровневый клавиатурный хук, который я уже успешно использовал несколько раз, но в последнее время он работает неправильно. Он считывает ввод с клавиатуры ровно 10 раз (10 раз с любой из клавиш, определенных в функции HookCallback), а затем останавливается. Это похоже на какую-то функцию безопасности ОС или какую-то другую программу, например, анивирус мешает и подавляет перехват клавиатуры после 10 раз.

Кто-нибудь еще сталкивался с этим ограничением в 10 раз? В чем может быть проблема, на ваш взгляд? Я использую Windows 7 64 Bit и бесплатный антивирус Avast. Программа написана на С# 2008.

Вот соответствующий код из program.cs:

 static class Program
{

    private const int WH_KEYBOARD_LL = 13;
    private const int WM_KEYDOWN = 0x0100;
    private static LowLevelKeyboardProc _proc = HookCallback;
    private static IntPtr _hookID = IntPtr.Zero;


    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool UnhookWindowsHookEx(IntPtr hhk);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr GetModuleHandle(string lpModuleName);

    private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);




    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        _hookID = SetHook(_proc);
        Application.Run(new Form1());
        UnhookWindowsHookEx(_hookID);
    }





    private static IntPtr SetHook(LowLevelKeyboardProc proc)
    {
        using (Process curProcess = Process.GetCurrentProcess())
        using (ProcessModule curModule = curProcess.MainModule)
        {
            return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
        }
    }

    private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
        {
            int vkCode = Marshal.ReadInt32(lParam);

            if ((Keys)vkCode == Keys.Delete)
            {
                Form1.staticmethod1();
            }
            else if ((Keys)vkCode == Keys.F8)
            {
                Form1.staticmethod2();
            }
            else if ((Keys)vkCode == Keys.F9)
            {
                Form1.staticmethod3();
            }

        }
        return CallNextHookEx(_hookID, nCode, wParam, lParam);
    }

Заранее спасибо.


person user3420118    schedule 14.03.2014    source источник
comment
Хотелось бы узнать ответ на этот вопрос!   -  person MEMark    schedule 14.03.2014
comment
Вы делаете что-нибудь странное внутри этих Form1.staticmethodX() методов?   -  person Damien_The_Unbeliever    schedule 14.03.2014
comment
Я скопировал и вставил ваш код дословно, и у меня нет этого ограничения. У меня работает безотказно. Какая у вас версия Windows и какие клавиши вы нажимаете? Вы каждый раз нажимаете одну и ту же клавишу (например, F9) или печатаете что-то сумасшедшее?   -  person Brandon    schedule 14.03.2014
comment
Чтение комментария от @Damien_The_Unbeliever также заставляет меня думать, что, возможно, эти методы формы блокируют ваш обратный вызов. Вы должны направить их, если можете, чтобы ваш код возвращал ваш следующий хук как можно скорее.   -  person Brandon    schedule 14.03.2014
comment
Windows защищает себя от неправильных обратных вызовов ловушки, она автоматически отменяет регистрацию ловушки, когда обратный вызов занимает слишком много времени. Время ожидания по умолчанию составляет 5 секунд. Вы делаете это неправильно, вместо этого используйте RegisterHotKey(). Отключение клавиши Delete для всех остальных программ очень неразумно.   -  person Hans Passant    schedule 14.03.2014
comment
@Damien_The_Unbeliever, уверяю вас, это не какой-то дискретный кейлоггер/шпионское ПО, которое я пишу. Это тот же самый код, который я использовал в нескольких программах, и раньше он работал, но сейчас он не работает ни в одной из них. Он отлично работает на моем старом компьютере с установленной Windows XP. Это создает проблему на моем 64-битном компьютере, на котором работает IWndows 7, а также установлен антивирус Avast. Поэтому я предполагаю, что это должно быть одно из двух. Я не уверена. Проблема не связана с тем, что находится внутри этих методов Form1.static.   -  person user3420118    schedule 14.03.2014
comment
@Hans Passant, он подавляется после 10 раз, даже если я нажимаю любую другую клавишу, определенную в обратном вызове, например F9 или F8.   -  person user3420118    schedule 14.03.2014
comment
Пользователям, которые задаются вопросом, связана ли эта программа с каким-то кейлоггером/трояном... Я не предпочитаю использовать сторонние инструменты, такие как autohotkey и т. д., и я пишу свои собственные инструменты для этих вещей, и здесь такие коды пригодятся.   -  person user3420118    schedule 14.03.2014
comment
Клиент по телефону: мои тормоза перестают работать после того, как я наступлю на них ровно 10 раз. Механик: такое может случиться, вам придется пригнать свою машину, чтобы я мог заглянуть под капот.   -  person Hans Passant    schedule 14.03.2014
comment
Я не думал, что это кейлоггер. Мне было интересно, как и то, что сказал Брэндон, - что вы можете делать что-то, что блокирует или связывает ресурсы, и это те ресурсы, которых на самом деле 10. Может быть, если бы вы могли добавить образец одного из них к вашему вопросу?   -  person Damien_The_Unbeliever    schedule 14.03.2014
comment
Извините за недоразумение. Я не публиковал ничего, кроме кода в Pogram.CS, потому что только это казалось важным, потому что статические методы в Form1, даже если я вызываю их, показывают только окно сообщения (MessageBox.Show()) или издают звуковой сигнал ( Consolee.Beep() не работает, функции вообще не вызываются после 10 раз, в простых методах MessageBox.Show() или Console.Beep() нет циклов и огромных ресурсов. каким-то образом блокируется / отключается после 10 раз.И мне очень любопытно узнать, откуда берется этот предел в 10 раз.   -  person user3420118    schedule 14.03.2014
comment
Ну, я не могу поручиться за 10 раз, но Messagebox.Show() - это блокирующий вызов. Я думаю, что больше склоняюсь к тому, что @HansPassant сказал выше о RegisterHotKey(), и что вы, вероятно, неправильно подходите к этому. Попробуйте это: нажмите клавишу, которая вызывает функцию MessageBox.Show(), и подождите 15 секунд, прежде чем закрыть окно сообщения. Затем попробуйте нажать клавишу еще раз и посмотреть, что произойдет.   -  person Brandon    schedule 14.03.2014
comment
Ханс Пассант прав. Я изменил код для использования с RegisterHotKey, и теперь он отлично работает. Что касается ограничения в 10 раз, то оно точно было из Windows 7. Я протестировал свою старую программу на виртуальной машине со свежеустановленной Windows 7, и возникла та же проблема.   -  person user3420118    schedule 15.03.2014
comment
Если вы полностью очистите статические методы, за исключением, скажем, увеличения счетчика и отображения счетчика с использованием другого потока, проблема исчезнет? Я столкнулся с тем же самым при использовании хуков Windows, в моем случае, потому что мой обработчик мыши рекурсивно запускал себя, что, по-видимому, Windows было достаточно умно, чтобы остановить.   -  person user21820    schedule 19.07.2014