我练习使用API32写了一个DLL,在任意窗口点击鼠标左键可查看该窗口的类名,可顺利通过调试。但程序运行一会就出现‘未处理的“System.NullReferenceException”类型的异常出现在 system.windows.forms.dll 中。其他信息: 未将对象引用设置到对象的实例。’谁能给分析一下,这是什么原因?
先将源码附上,请大家共同探讨。
//以下为DLL类库源码
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace MHook
{
/// <summary>
/// Class1 的摘要说明。
/// </summary>
public class MouseHook
{
public MouseHook()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
#region //********API32函数声明**************
// **********************************************************************
// Win32: SetWindowsHookEx()
[DllImport("user32.dll",CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
private static extern IntPtr SetWindowsHookEx(HookType code,
HookProc func,
IntPtr hInstance,
int threadID);
// Win32: UnhookWindowsHookEx()
[DllImport("user32.dll",CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
private static extern int UnhookWindowsHookEx(IntPtr hhook);
// Win32: CallNextHookEx()
[DllImport("user32.dll",CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
private static extern int CallNextHookEx(IntPtr hhook,
int nCode, int wParam, IntPtr lParam);
// Win32: GetModuleHandle()
[DllImport("kernel32.dll",CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
// Win32: GetForegroundWindow()
[DllImport( "user32.dll",CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
private static extern IntPtr GetForegroundWindow();
// Win32: GetWindowThreadProcessId()
[DllImport("user32.dll",CharSet=CharSet.Auto)]
private static extern int GetWindowThreadProcessId (
IntPtr hwnd,
int lpdwProcessId
);
// Win32: GetCurrentThreadId
[DllImport("kernel32.dll", EntryPoint="GetCurrentThreadId")]
public static extern int GetCurrentThreadId ();
// Win32: AttachThreadInput()
[DllImport("user32.dll",CharSet=CharSet.Auto)]
private static extern int AttachThreadInput (
int idAttach,
int idAttachTo,
int fAttach
);
// Win32: GetFocus()
[DllImport("user32.dll",CharSet=CharSet.Auto)]
private static extern IntPtr GetFocus ();
// Win32: SendMessage()
[DllImport("user32.dll",CharSet=CharSet.Auto)]
private static extern int SendMessage (
HandleRef hwnd,
int wMsg,
int wParam,
int lParam
);
[DllImport("user32.dll", EntryPoint="SendMessage",CharSet=CharSet.Auto)]
public static extern int SendMessageString (
HandleRef hwnd,
int wMsg,
int wParam,
StringBuilder lParam
);
// Win32: GetWindowText()
[DllImport("user32.dll",CharSet=CharSet.Auto)]
private static extern int GetWindowText (
IntPtr hwnd,
StringBuilder lpString,
int nMaxCount
);
// Win32: GetClassName()
[DllImport("user32.dll",CharSet=CharSet.Auto)]
private static extern int GetClassName (
IntPtr hwnd,
StringBuilder lpClassName,
int nMaxCount
);
#endregion
//enum HookType
private enum HookType : int
{
//WH_JOURNALRECORD = 0,
//WH_JOURNALPLAYBACK = 1,
//WH_KEYBOARD = 2,
//WH_GETMESSAGE = 3,
//WH_CALLWNDPROC = 4,
//WH_CBT = 5,
//WH_SYSMSGFILTER = 6,
//WH_MOUSE = 7,
//WH_HARDWARE = 8,
//WH_DEBUG = 9,
//WH_SHELL = 10,
//WH_FOREGROUNDIDLE = 11,
//WH_CALLWNDPROCRET = 12,
//WH_KEYBOARD_LL = 13,
WH_MOUSE_LL = 14
}
// Filter function delegate
private delegate int HookProc(int nCode, int wParam, IntPtr lParam);
// **********************************************************************
//指向钩子处理函数,该函数是自定义的而由Window系统调用的函数,即回调函数
// **********************************************************************
private const int WM_LBUTTONUP=0x0202;
private const int WM_SETTEXT=0x000C;
private const int WM_PAINT= 0x000F;
private static IntPtr hookWnd =IntPtr.Zero;
private static HandleRef txtHandle;
private static StringBuilder lpClassName = new StringBuilder("Hello!",256);
//*************************************************************************
public static bool SetHook(HandleRef myHandle)
{
IntPtr dllInstance = GetModuleHandle("MHook.dll");
if (dllInstance==IntPtr.Zero)
{
return false;
}
else
{
txtHandle = myHandle;
hookWnd=SetWindowsHookEx(
HookType.WH_MOUSE_LL,
new HookProc(MouseHook.MyMouseProc),
dllInstance,
0);
if (hookWnd==IntPtr.Zero)
{
return false;
}
return true;
}
}
public static void StopHook()
{
UnhookWindowsHookEx(hookWnd );
}
private static int MyMouseProc(int nCode, int wParam, IntPtr lParam)
{
if(nCode<0)
{
return CallNextHookEx(hookWnd,nCode,wParam,lParam);
}
else if(wParam==WM_LBUTTONUP)
{
myProc();
return CallNextHookEx(hookWnd,nCode,wParam,lParam);
}
else
{
//调用钩子函数链,以便使其他应用程序能够正常工作
return CallNextHookEx(hookWnd,nCode,wParam,lParam);
}
}
private static bool myProc()
{
//获得当前活动窗口句柄
IntPtr foreWnd = GetForegroundWindow();
if (foreWnd==IntPtr.Zero)
{
return false;
}
//获得活动窗口的线程号
int threadforeground = GetWindowThreadProcessId(foreWnd, 0);
if (threadforeground==0)
{
return false;
}
//获得与自己程序的窗口相关的线程号
int threadthis = GetCurrentThreadId();
if (threadthis==0)
{
return false;
}
//将两个线程的输入联系起来,GetFocus函数获得其它线程中的焦点窗口
int attchFlag =AttachThreadInput(threadthis,threadforeground,1);
//得到当前的具有输入焦点的子窗口
IntPtr subWnd = GetFocus();
if (subWnd==IntPtr.Zero)
{
return false;
}
//获得当前的具有输入焦点的子窗口的主窗口的类名
int getClassFlag = GetClassName(subWnd,lpClassName,lpClassName.Capacity);
if (getClassFlag==0)
{
return false;
}
AttachThreadInput(threadthis, threadforeground, 0);
int sendMsgFlag1 = SendMessageString(txtHandle,WM_SETTEXT,0,lpClassName);
if (sendMsgFlag1==0)
{
return false;
}
int sendMsgFlag2 = SendMessage(txtHandle,WM_PAINT,0,0);
if (sendMsgFlag2==0)
{
return false;
}
return true;
}
}
}
//以下是主程序,很简单,只是简单调用了DLL中函数
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using MHook;
using System.Runtime.InteropServices;
namespace testhook
{
/// <summary>
/// Form1 的摘要说明。
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.TextBox textBox1;
//private int hookHandle;
private System.Windows.Forms.Button button1;
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.Container components = null;
public Form1()
{
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();
//
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
//
}
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows 窗体设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.textBox1 = new System.Windows.Forms.TextBox();
this.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(48, 104);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(384, 28);
this.textBox1.TabIndex = 0;
this.textBox1.Text = "textBox1";
//
// button1
//
this.button1.Location = new System.Drawing.Point(128, 168);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(136, 40);
this.button1.TabIndex = 1;
this.button1.Text = "button1";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(10, 21);
this.ClientSize = new System.Drawing.Size(480, 267);
this.Controls.Add(this.button1);
this.Controls.Add(this.textBox1);
this.Name = "Form1";
this.Text = "Form1";
this.TopMost = true;
this.Closing += new System.ComponentModel.CancelEventHandler(this.Form1_Closing);
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void Form1_Load(object sender, System.EventArgs e)
{
HandleRef hrTextBox=new HandleRef(textBox1,textBox1.Handle);
if((MouseHook.SetHook(hrTextBox))==false)
MessageBox.Show ("安装钩子失败!");
}
private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
MouseHook.StopHook();
}
private void button1_Click(object sender, System.EventArgs e)
{
;
}
}
}