2011-04-07 25 views
5

私はC#でキーロガーを作成していますが、キーボードイベントから呼び出されるフックメソッドを取得する際に問題があります。私のコードは正しく表示されますが、何らかの理由でコールバックが起こっていません。ここで .NETアプリケーションで低レベルのキーボードフックが呼び出されない

は、関連するコードです:

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

[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 const int WH_KEYBOARD_LL = 13; 
private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam); 
private static IntPtr HookHandle = IntPtr.Zero; 

static void Main() 
{ 
    /* install low level global keyboard hook */ 
    HookHandle = SetWindowsHookEx(WH_KEYBOARD_LL, HookCallback, GetModuleHandle(null), 0); 

    /* every 60 seconds, process collected keystrokes */ 
    for (;;) 
    { 
     Thread.Sleep(60000); 
     SendKeyData(); 
    } 
} 

private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) 
{ 
    /* code to handle key events would be here */ 

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

private static void SendKeyData() 
{ 
    /* code to send accumulated keystroke data to remote server would be here */ 
} 

SetWindowsHookExコール(すなわちNOT NULL)それが必要としてハンドルを返すので、それがインストールされていることを意味する必要がありますが、私はHookCallbackにブレークポイントを置くときそれは決して達成されません。

誰でも私が間違っているかもしれないことをアドバイスできますか?

+1

'for'ブロックをコメントアウトすると動作しますか? –

+0

いいえ、私がそれをしてもプロセスはただちに終了しません。 –

+2

無限のforループの代わりにTimerを使用する方が良いでしょう。少なくともタイマーでは、必要に応じて停止することができます。 – jlafay

答えて

4

コンソールアプリケーションを作成しているようです。これはフォームアプリケーションでなければなりません。ウィンドウイベントを処理しているからです。フォームを隠すだけで動作します。コンソールアプリケーションのための回避策として

、あなたのループ内でApplication.DoEvents()を呼び出すことができます。

for (;;) 
{ 
    Thread.Sleep(1); 
    Application.DoEvents(); //Process event queue 
    SendKeyData(); 
} 

悪、良いではないためにこれを使用してください。

+0

1分寝ていないと、フックのタイムアウトが発生します。 45ミリ秒は幸せな数字です。 Application.Run()が優れています。 –

+0

多くの感謝!両方の回答の組み合わせによって、私は成功した結果に導かれました。私は明白なメッセージループが必要であることを認識しませんでした。これで私のプログラムはApplication.Run()を呼び出し、キーデータの送信はBackgroundWorker(同期キューを介して2つのスレッド間の通信)を介して別のスレッドを使用して行われます。私は作業コードで質問を更新します。 –

+0

'sleep 'を使う必要があるなら' sleep(1) 'を使います。このコードはすべてのキーボード入力を遅延させ、IMOは@HansPassantが示唆するように45msの両方を遅延させ、450msは受け入れられません。正しい解決策は、ブロッキングメッセージのディスパッチですが、winapi関数を直接呼び出すことなく、C#のコンソールアプリケーションでそれを行う方法は考えられません。 – CodesInChaos

0

GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName) 

のGetModuleHandle(ヌル)を交換してみてください、それはトリックを行うかどうかを確認します。 GetCurrentProcess()から返されたProcessオブジェクトとMainModuleから返されたProcessModuleオブジェクトは両方とも使い捨てであるため、それらを変数として宣言してから手動で破棄したい場合があります。さらに良いものをusingブロックに入れてください。

+0

返信いただきありがとうございますが、それは問題ではありませんでした - SetWindowsHookExのパラメータには当初問題がありましたが、グローバルフックの現在のプロセスのモジュールハンドルが必要なときにスレッドIDのパラメータを間違えて入れました。 –

関連する問題