티스토리 뷰

반응형

using System;

using System.Runtime.InteropServices;

 

namespace MouseHookLib

{

    public static class GlobalMouseHook

    {

        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]

        public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

 

        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]

        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, IntPtr wParam, IntPtr lParam);

 

        public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);

    }

}

System.Runtime.InteropServicesusing 해줘야 마이그레이션을 할 수 있다.

다음은 마이그레이션 코드이다.

[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]

 

CC++에서는 여러가지 메시지 후크를 할 수 있지만, .Net에서는 dll을 참조하는 방법으로 마우스와 키보드만 후킹할 수 있다. 다음 코드는 메시지가 바로 출력되기 전에 후크함수를 두어서 후킹하는 코드이다.

 

public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

위는 훅 프로시저를 설치할 때 쓰이는 함수이다.

idHook : 설치하고자 하는 훅의 타입을 지정아며 WH_로 시작되는 메크로 상수중 하나를 써 주면 된다.

Lpfn : 훅 프로시저의 번지이다.

hMod : 훅 프로시저를 가진 인스턴트 핸들이다.

dwThreadId : 훅 프로시저가 감시할 스레드의 ID 이며 값이 0이면 시스템의 모든 스레드에서 발생하는 메시지가 훅 프로시저로 전달된다.

 

public static extern bool UnhookWindowsHookEx(int idHook);

위는 훅 프로시저를 해제하는 함수이다.

idHook: 해제하고자 하는 훅 핸들

 

public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);

위는 다음 훅 프로시저에게 전해주는 함수이다.

idHook: 현재 처리하고 있는 훅의 핸들인데 SetWindowsHeekEX 함수가 리턴한 값이다.

nCode, wParam, lParam : 운영체제가 훅 프로시저에게 전달 해준 인수들이다.

 

public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);

대리자 형식의 훅프로시저함수이다. 무슨 일을 하는지 서로에게 알려주기위해 만들었다.

 

다음은 마우스를 후크하는 코드이다.

public static class MouseHook  {

        [StructLayout(LayoutKind.Sequential)]

        public class POINT

        {

            public int x;

            public int y;

        }

        [StructLayout(LayoutKind.Sequential)]

        public class MouseHookStruct

        {

            public POINT pt;

            public int hwnd;

            public int wHitTestCode;

            public int dwExtraInfo;

        }

        public const int WH_MOUSE_LL = 14;

 

        public static int hookHandle = 0;

        private static HookProc callbackDelegate;

        public static void StartHook()

        {

            callbackDelegate = new HookProc(CallBack);

            if(hookHandle != 0)

            {

                return;

            }          

            hookHandle = GlobalMouseHook.SetWindowsHookEx(WH_MOUSE_LL, callbackDelegate, IntPtr.Zero, 0);

        }

        public static void StopHook()

        {

            GlobalMouseHook.UnhookWindowsHookEx(hookHandle);

        }

        public static int CallBack(int nCode, IntPtr wParam, IntPtr lParam)

        {

            MouseHookStruct mouseInput = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));

            System.Diagnostics.Debug.WriteLine(mouseInput.pt.x + " : " + mouseInput.pt.y);

 

            return GlobalMouseHook.CallNextHookEx(hookHandle, nCode, wParam, lParam);           

        }

    }

[StructLayout(LayoutKind.Sequential)]

비관리코드로 개체의 레이아웃을 제어하는 코드이다.

 

.Net에서는 앞서서 말했듯이 마우스와 키보드의 후킹만이 가능한데,

기존의 WH_MOUSE = 7 WH_KEYBORAD = 2대신에

WH_MOUSE_LL = 14WH_KEYBORAD_LL = 13을 쓰고, LL붙은 변수들은

Windows NT/2000/XP/Vista/7/8.1/10에서 쓸 수 있다.

 

그리고 dll 만들어준 대리자함수를 관리하기 위해 관리코드를 한 줄 적어준다.

public static void StartHook()

        {

            if (callbackDelegate != null) throw new InvalidOperationException("hook error");

            callbackDelegate = new HookProc(CallBack);

            if(hookHandle != 0)

            {

                return;

            }          

            hookHandle = GlobalMouseHook.SetWindowsHookEx(WH_MOUSE_LL, callbackDelegate, IntPtr.Zero, 0);

        }

 

SetWindowsHookEx인자에 필자는 기존의 그냥 CallBack함수를 적었더니, 비관리 코드 에러가 떠서 msdn에 찾아보니 The callbackOnCollectedDelegate managed debugging assistant (MDA) is activated if a delegate is marshaled from managed to unmanaged code as a function pointer and a callback is placed on that function pointer after the delegate has been garbage collected.라고 하더라. 그냥 비관리 코드를 호출하면서 대리자를 넘겼으나, 해당 대리자가 가비지 수집되면서 발생하는 오류이다.

실행화면은 다음과 같다.


반응형

'C#' 카테고리의 다른 글

블루투스 동글을 이용한 PC Lock  (1) 2016.10.26
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함