1. 程式人生 > >C# 全域性鉤子 方法二

C# 全域性鉤子 方法二

//網上都說,我的朋友也說C#不能實現全域性鉤子獲得listView之類的訊息,只能實現全域性的鍵盤和滑鼠鉤子,下面程式碼是在做得到其它程式的listView控制元件中的列表寫的,不過沒實現,專案只做了一半放下了,改其它方法實現了,本程式碼只供參考學習,如果哪位高手朋友做出來了,請把程式碼發一下,本人會非常感謝,再感謝的!!

using System;
using System.Collections.Generic;

using System.Text;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Diagnostics;
 

namespace AnShieldClassLibrary
{
   
        //public struct tagCWPSTRUCT
        //{
        //    public  IntPtr lParam;// 訊息引數 
        //    public  IntPtr wParam;// 訊息引數 
        //    public  int message;// 訊息值,由非負整數來表示
        //    public  IntPtr hwnd;// 訊息的目的地控制代碼
        //}
    

       [StructLayout(LayoutKind.Sequential)]
       public struct tagCWPSTRUCT
       {
           public IntPtr lParam;// 訊息引數 
           public IntPtr wParam;// 訊息引數 
           public int message;// 訊息值,由非負整數來表示
           public IntPtr hwnd;// 訊息的目的地控制代碼

           //public IntPtr lparam;
           //public IntPtr wparam;
           //public int message;
           //public IntPtr hwnd;
           //以前的
           //public int message;
           //public int paramL;
           //public int paramH;
           //public int Time;
           //public int hwnd;
       }
       //訊息結構體
       [StructLayout(LayoutKind.Sequential)]
       public struct LVITEM
       {
           public int mask;
           public int iItem;
           public int iSubItem;
           public int state;
           public int stateMask;
           public string pszText; // string
           public int cchTextMax;
           public int iImage;
           public IntPtr lParam;
           public int iIndent;
           public int iGroupId;
           public int cColumns;
           public IntPtr puColumns;
       }
       //不用鉤子得到視窗訊息
       [StructLayout(LayoutKind.Sequential)]
       public struct CwpStruct
       {
           public IntPtr lparam;
           public IntPtr wparam;
           public int message;
           public IntPtr hwnd;
       }
       [StructLayout(LayoutKind.Sequential)]
       public struct DebugStruct
       {
           IntPtr idThread;
           IntPtr idThreadInstaller;
           IntPtr lParam;
           IntPtr wParam;
           int code;
       }
      [StructLayout(LayoutKind.Sequential)]
       public struct EventMsg
       {
           public int message;
           public int paramL;
           public int paramH;
           public int Time;
           public IntPtr hwnd;
       }

   public  class WanGuaClass
    {

        static int Lvm_First = 0x0000f;
        static int warningHook = 0;//控制代碼
        string strBarCode = "";

        public const int OPEN_PROCESS_ALL = 2035711;
        public const int PAGE_READWRITE = 4;
        public const int PROCESS_CREATE_THREAD = 2;
        public const int PROCESS_HEAP_ENTRY_BUSY = 4;
        public const int PROCESS_VM_OPERATION = 8;
        public const int PROCESS_VM_READ = 256;
        public const int PROCESS_VM_WRITE = 32;

        private const int PAGE_EXECUTE_READWRITE = 0x4;
        private const int MEM_COMMIT = 4096;
        private const int MEM_RELEASE = 0x8000;
        private const int MEM_DECOMMIT = 0x4000;
        private const int PROCESS_ALL_ACCESS = 0x1F0FFF;

        //查詢窗體
         [DllImport("user32.dll", EntryPoint = "FindWindow", CharSet = CharSet.Auto)]
        public extern static IntPtr FindWindow(string lpClassName, string lpWindowName);
        [DllImport("User32.dll", EntryPoint = "FindWindowEx", CharSet = CharSet.Auto)]
        public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpClassName, string lpWindowName);

        //將指定的訊息傳送到一個或多個視窗
        [DllImport("user32.dll", EntryPoint = "SendMessage")]
        public static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
        [DllImport("user32.dll",EntryPoint="SendMessage")]
        public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, [MarshalAs(UnmanagedType.LPStr)] string lParam);

        //傳送後等待處理完才返回
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        public static extern int SendMessage(IntPtr wnd, int msg, IntPtr wP, IntPtr lP);
        [DllImport("User32.dll", EntryPoint = "PostMessage")]
        public static extern int PostMessage(IntPtr wnd, int msg, IntPtr wP, IntPtr lP);//傳送完不管結果就返回
        [DllImport("User32.dll", EntryPoint = "SetForegroundWindow")]//啟用視窗
        public static extern int SetForegroundWindow(IntPtr hwnd);


        //得到目標程序控制代碼的函式
        [DllImport("User32.DLL")]
        public extern static int GetWindowThreadProcessId(int hwnd, ref IntPtr lpdwProcessId);
        [DllImport("User32.DLL")]
        public extern static int GetWindowThreadProcessId(IntPtr hwnd, ref IntPtr lpdwProcessId);

        //開啟程序
        [DllImport("kernel32.dll")]
        public extern static int OpenProcess(int dwDesiredAccess,int bInheritHandle,int dwProcessId);
        [DllImport("kernel32.dll")]
        public extern static IntPtr OpenProcess( uint dwDesiredAccess,int bInheritHandle, uint dwProcessId);

        //關閉控制代碼的函式
        [DllImport("kernel32.dll", EntryPoint = "CloseHandle")]
        public static extern int CloseHandle(int hObject);
      
        //獲取訊息
        [DllImport("user32", EntryPoint = "GetMessage")]
        public static extern int GetMessage(out CwpStruct lpMsg, IntPtr hwnd, int wMsgFilterMin, int wMsgFilterMax);
     
        //讀記憶體
        [DllImport("Kernel32.dll ")]
        public static extern Int32 ReadProcessMemory(IntPtr hProcess,IntPtr lpBaseAddress,[In, Out] byte[] buffer, int size,out IntPtr lpNumberOfBytesWritten);
        [DllImport("Kernel32.dll ")]
        public static extern Int32 ReadProcessMemory( int hProcess, int lpBaseAddress,ref int buffer,int size,int lpNumberOfBytesWritten);
        [DllImport("Kernel32.dll ")]
        public static extern Int32 ReadProcessMemory(int hProcess, int lpBaseAddress, byte[] buffer, int size, int lpNumberOfBytesWritten );

        //寫記憶體
        [DllImport("kernel32.dll")]
        public static extern Int32 WriteProcessMemory(IntPtr hProcess,IntPtr lpBaseAddress,[In, Out] byte[] buffer, int size, out IntPtr lpNumberOfBytesWritten );

        [DllImport("kernel32.dll")]
        public static extern Int32 WriteProcessMemory(int hProcess, int lpBaseAddress, byte[] buffer,int size,int lpNumberOfBytesWritten );
      
        //建立執行緒
        [DllImport("kernel32", EntryPoint = "CreateRemoteThread")]
        public static extern int CreateRemoteThread(int hProcess, int lpThreadAttributes,int dwStackSize, int lpStartAddress, int lpParameter,int dwCreationFlags, ref int lpThreadId);

        //開闢指定程序的記憶體空間
        [DllImport("Kernel32.dll")]
        public static extern System.Int32 VirtualAllocEx(System.IntPtr hProcess,System.Int32 lpAddress,System.Int32 dwSize,System.Int16 flAllocationType, System.Int16 flProtect );

        [DllImport("Kernel32.dll")]
        public static extern System.Int32 VirtualAllocEx( int hProcess,int lpAddress,int dwSize, int flAllocationType,int flProtect);
       
        //彈視窗
        [DllImport("user32.dll")]
        public static extern int MessageBoxA(int h, string m, string c, int type);

        //釋放記憶體空間
        [DllImport("Kernel32.dll")]
        public static extern System.Int32 VirtualFreeEx(int hProcess,int lpAddress,int dwSize,int flAllocationType);      
     
        // 安裝鉤子  
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
        // 解除安裝鉤子
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        private static extern bool UnhookWindowsHookEx(int idHook);
        // 繼續下一個鉤子
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        private static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);

        //當前模組控制代碼:GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName)
        [DllImport("kernel32.dll")]
        public static extern IntPtr GetModuleHandle(string name);

        //宣告定義回撥函式
        delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);

       //CwpStruct cwpStruct = new CwpStruct();
       //static int LVM_FIRST = 0x1000;
       //static int LVM_INSERTITEMA = LVM_FIRST + 7;
       //static int LVM_SETITEMTEXT = LVM_FIRST + 46;
       //////////
       public const int WH_CALLWNDPROC = 4; //mouse hook constant
       public const int LVM_FIRST = 0x1000;
       public const int LVM_INSERTITEM = LVM_FIRST + 7;//1列     
       public const int LVM_INSERTITEMW = LVM_FIRST + 77;//1列
       public const int LVM_SETITEMTEXT = LVM_FIRST + 46;//2列
       public const int LVM_SETITEMTEXTW = LVM_FIRST + 116;//2列
       HookProc MouseHookProcedure; //Declare MouseHookProcedure as HookProc type.
       /// <summary>
       /// 委託
       /// </summary>
       /// <param name="nCode">鉤子型別</param>
       /// <param name="wParam"></param>
       /// <param name="lParam"></param>
       /// <returns></returns>
       public int WarningMsg(int nCode, Int32 wParam, IntPtr lParam)
        {
            tagCWPSTRUCT lp = (tagCWPSTRUCT)Marshal.PtrToStructure(lParam, typeof(tagCWPSTRUCT));
        
            if (lp.message == LVM_INSERTITEM || lp.message == LVM_INSERTITEMW)
            {               
               
                MessageBoxA(0, "範圍是A!", "描述", 0);
              
            }
            else if (lp.message == LVM_SETITEMTEXT || lp.message == LVM_SETITEMTEXTW)
            {            
                MessageBoxA(0, "範圍是B!", "描述", 0);
       
            }

            //tagCWPSTRUCT msg = (tagCWPSTRUCT)Marshal.PtrToStructure((IntPtr)lParam, typeof(tagCWPSTRUCT));              
            //if (msg.message == LVM_SETITEMTEXT)
            //{
            //    MessageBoxA(0, "取資料成功!", "描述", 0);
            //}
                //try
            {           

                /*
                tagCWPSTRUCT msg = (tagCWPSTRUCT)Marshal.PtrToStructure(lParam, typeof(tagCWPSTRUCT));              
                IntPtr loginHwnd = AnShieldClassLibrary.WanGuaClass.FindWindow(null, "MyList"); //找到視窗控制代碼  
                IntPtr ListHwnd = IntPtr.Zero;
                IntPtr listThreadId =IntPtr .Zero;

                if (loginHwnd != IntPtr.Zero)
                {
                    ListHwnd = AnShieldClassLibrary.WanGuaClass.FindWindowEx(loginHwnd, IntPtr.Zero, "SysListView32", null);//列表控制代碼
                    GetWindowThreadProcessId(ListHwnd, ref  listThreadId);
                  
                   // tagCWPSTRUCT msg = (tagCWPSTRUCT)Marshal.PtrToStructure(lParam, typeof(tagCWPSTRUCT));
                   
                    //if (msg.message == LVM_FIRST)
                    //{
                    //    //LVITEM pLvitem = (LVITEM)cwpStruct;
                    //    //MessageBoxA(0, "取資料成功!", "描述", 0);
                    //}
                    //if (msg.message == LVM_SETITEMTEXT)
                    //{
                    //    MessageBoxA(0, "取資料成功!", "描述", 0);
                    //}
                    
                     if (msg.hwnd == ListHwnd)
                    {
                                              
                            ////內容
                            if (msg.message == Lvm_First)
                            {
                                MessageBoxA(0, "訊息取得成功!", "描述", 0);
                            
                            }
                            else
                            {
                                MessageBoxA(0, "成功!", "描述", 0);
                             
                            }                     
                    }
                    else
                    {                      
                      
                         MessageBoxA(0, "訊息取得成功!", "描述", 0);MessageBoxA(0, "目標執行緒:"+listThreadId+";;loginHwnd:" + loginHwnd + "  message:" + msg.message + "  hwnd:" + msg.hwnd +"  msg"+msg+ "  (nCode:"+nCode+" wParam:"+wParam+" LParam:"+lParam+")", "描述", 0);
                      
                    }
                }
                 * */              
                //return CallNextHookEx(warningHook, nCode, wParam, lParam);
            }
            //catch ( Exception ex) {
                //MessageBoxA(0, ex.ToString(), "錯誤資訊", 0);
                return CallNextHookEx(warningHook, nCode, wParam, lParam);
            //}            
        }

    
      
       
        // 安裝鉤子
        public int Start()
        {
           
                if (warningHook == 0)
                {
                    //IntPtr loginHwnd = AnShieldClassLibrary.WanGuaClass.FindWindow(null, "MyList"); //找到視窗控制代碼  
                    //if (loginHwnd != IntPtr.Zero)
                    {
                        //IntPtr ListHwnd = AnShieldClassLibrary.WanGuaClass.FindWindowEx(loginHwnd, IntPtr.Zero, "SysListView32", null);//列表控制代碼
                       // if (ListHwnd != IntPtr.Zero)
                        {
                            //WH_CALLWNDPROC = 4 
                            IntPtr lockHwnd = Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]);
                            warningHook = SetWindowsHookEx(4, new HookProc(WarningMsg), lockHwnd, 0);// // 安裝鉤子    
                            //warningHook = SetWindowsHookEx(4, new HookProc(WarningMsg), GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);
                        }

                    }


                }
          
            return warningHook;
        }

        // 解除安裝鉤子  
        public bool Stop()
        {
            bool b = false;
            if (warningHook != 0)
            {
                b= UnhookWindowsHookEx(warningHook);
            }
            return b;
        }
    }
}

//網上都說,我的朋友也說C#不能實現全域性鉤子獲得listView之類的訊息,只能實現全域性的鍵盤和滑鼠鉤子,上面程式碼是在做得到其它程式的listView控制元件中的列表寫的,不過沒實現,專案只做了一半放下了,改其它方法實現了,本程式碼只供參考學習,如果哪位高手朋友做出來了,請把程式碼發一下,本人會非常感謝,再感謝的!!