마우스를 후킹하는 방법

 

Nuget 에서 MouseKeyHook 를 설치

 

프로그램 생성자나 원하는 후킹시점에 아래 처럼 코딩

 

using System.Windows.Forms;

 

using Gma.System.MouseKeyHook;

 

namespace MouseHooking

{

    public partial class MainForm : Form

    {

        public MainForm()

        {

            InitializeComponent();

 

            Hook.GlobalEvents().MouseDown += (s, e) =>

            {

                this.hookTextBox.AppendText($"Mouse {e.Button} Down / ");

            };

 

            Hook.GlobalEvents().MouseDoubleClick += (s, e) =>

            {

                this.hookTextBox.AppendText($"Mouse {e.Button} button double clicked / ");

            };

 

            Hook.GlobalEvents().MouseWheel += (s, e) =>

            {

                this.hookTextBox.AppendText($"Mouse wheel / ");

            };

 

            Hook.GlobalEvents().MouseDragStarted += (s, e) =>

            {

                this.hookTextBox.AppendText($"Mouse drag start / ");

            };

 

            Hook.GlobalEvents().MouseDragFinished += (s, e) =>

            {

                this.hookTextBox.AppendText($"Mouse drag finish / ");

            };

        }

    }

}

 

 

프로그램을 띄우면 마우스가 어디있건 움직임을 후킹한다.

 

using System.Collections.Generic;

using System.IO;

using System.Text.RegularExpressions;

 

namespace TEST

{

    class Function

    {

        public static List<string> GetImageFiles(string directoryPath)

        {

            List<string> imageFileList = new List<string>();

 

            foreach (string fileName in Directory.GetFiles(directoryPath))

            {

                if (Regex.IsMatch(fileName, @".jpg|.png|.bmp|.JPG|.PNG|.BMP|.JPEG|.jpeg$"))

                {

                    imageFileList.Add(fileName);

                }

            }

 

            return imageFileList;

        }

    }

}

 

 

다른 프로그램의 키입력을 후킹하고 싶을 때 처리하는 코드입니다.

 

using System;

using System.Runtime.InteropServices;

using System.Windows.Forms;

 

namespace Hooking

{

    public partial class MainForm : Form

    {

        [DllImport("user32.dll")]

        static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc callback, IntPtr hInstance, uint threadId);

 

        [DllImport("user32.dll")]

        static extern bool UnhookWindowsHookEx(IntPtr hInstance);

 

        [DllImport("user32.dll")]

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

 

        [DllImport("kernel32.dll")]

        static extern IntPtr LoadLibrary(string lpFileName);

 

        private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

 

        const int WH_KEYBOARD_LL = 13;

        const int WM_KEYDOWN = 0x100;

 

        private IntPtr hook = IntPtr.Zero;

 

 

        public MainForm()

        {

            InitializeComponent();

 

            this.Load += MainForm_Load;

            this.FormClosing += MainForm_Closing;

        }

 

        private void SetHook()

        {

            IntPtr hInstance = LoadLibrary("User32");

 

            hook = SetWindowsHookEx(WH_KEYBOARD_LL, HookProc, hInstance, 0);

        }

 

        private void UnHook()

        {

            UnhookWindowsHookEx(hook);

        }

 

        private IntPtr HookProc(int code, IntPtr wParam, IntPtr lParam)

        {

            if (code >= 0 && wParam == (IntPtr)WM_KEYDOWN)

            {

                int vkCode = Marshal.ReadInt32(lParam);

 

                // 키 입력에 따른 처리를 추가합니다.

                if (vkCode.ToString() == "17")

                {

                    this.hookTextBox.AppendText("CTRL");

                }

                else if (vkCode.ToString() == "91")

                {

                    this.hookTextBox.AppendText("LEFT WINDOW");

                }

                else if (vkCode.ToString() == "18")

                {

                    this.hookTextBox.AppendText("ALT");

                }

                else if (vkCode.ToString() == "32")

                {

                    this.hookTextBox.AppendText("SPACE BAR");

                }

                else if (vkCode.ToString() == "92")

                {

                    this.hookTextBox.AppendText("RIGHT WINDOW");

                }

                else if (vkCode.ToString() == "93")

                {

                    this.hookTextBox.AppendText("SELECT KEY");

                }

                else if (vkCode.ToString() == "16")

                {

                    this.hookTextBox.AppendText("SHIFT");

                }

                else if (vkCode.ToString() == "20")

                {

                    this.hookTextBox.AppendText("CAPS LOCK");

                }

                else if (vkCode.ToString() == "9")

                {

                    this.hookTextBox.AppendText("TAB");

                }

                else if (vkCode.ToString() == "96")

                {

                    this.hookTextBox.AppendText("numpad 0");

                }

                else if (vkCode.ToString() == "97")

                {

                    this.hookTextBox.AppendText("numpad 1");

                }

                else if (vkCode.ToString() == "98")

                {

                    this.hookTextBox.AppendText("numpad 2");

                }

                else if (vkCode.ToString() == "99")

                {

                    this.hookTextBox.AppendText("numpad 3");

                }

                else if (vkCode.ToString() == "100")

                {

                    this.hookTextBox.AppendText("numpad 4");

                }

                else if (vkCode.ToString() == "101")

                {

                    this.hookTextBox.AppendText("numpad 5");

                }

                else if (vkCode.ToString() == "102")

                {

                    this.hookTextBox.AppendText("numpad 6");

                }

                else if (vkCode.ToString() == "103")

                {

                    this.hookTextBox.AppendText("numpad 7");

                }

                else if (vkCode.ToString() == "104")

                {

                    this.hookTextBox.AppendText("numpad 8");

                }

                else if (vkCode.ToString() == "105")

                {

                    this.hookTextBox.AppendText("numpad 9");

                }

 

                this.hookTextBox.AppendText(" | "); // 구분자

 

                return CallNextHookEx(hook, code, (int)wParam, lParam); // 키입력을 정상적으로 동작하게 합니다.

 

                //return (IntPtr)1; // 키입력을 무효화 합니다.

            }

            else

            {

                return CallNextHookEx(hook, code, (int)wParam, lParam);

            }

        }

 

        private void MainForm_Load(object sender, EventArgs e)

        {

            SetHook();

        }

 

        private void MainForm_Closing(object sender, System.ComponentModel.CancelEventArgs e)

        {

            UnHook();

        }

    }

}

 

 

 

어떤 프로그램이든 키보드 입력한 경우 아래처럼 후킹되어 표시됩니다.

 

솔루션의 프로젝트들의 전체 라인수를 알아내는 방법


분석 > 코드 메트릭 계산 > 솔루션

* '선택한 프로젝트'를 선택하면 프로젝트만 결과 도출

아래처럼 각 프로젝트별/ 네입스페이스별 라인수가 보여진다.

액셀버튼을 이용해 액셀파일로도 저장할 수 있다. (노란색 네모박스 표시)

액셀 저장 결과




특정파일을 Windows  탐색기를 열어 선택하게 하는 코드

1.

using System.IO;

string filePath = @"D:\test.txt"; // 선택할 파일 


if (!File.Exists(filePath))

{

    return;

}


string argument = "/select, \"" + filePath + "\"";


System.Diagnostics.Process.Start("Explorer.exe", argument);



2.

[DllImport("shell32.dll", ExactSpelling = true)]

public static extern void ILFree(IntPtr pidlList);


[DllImport("shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]

public static extern IntPtr ILCreateFromPathW(string pszPath);


[DllImport("shell32.dll", ExactSpelling = true)]

public static extern int SHOpenFolderAndSelectItems(IntPtr pidlList, uint cild, IntPtr children, uint dwFlags);


string filePath = @"D:\test.txt"; // 선택할 파일 


var pidl = ILCreateFromPathW(filePath);

SHOpenFolderAndSelectItems(pidl, 0, IntPtr.Zero, 0);


ILFree(pidl);



아래 코드를 이용하면 캡쳐를 방지할 수 있습니다.

using System;

using System.Drawing;

using System.Runtime.InteropServices;

using System.Windows.Forms;


namespace WindowsFormsApp

{

    public partial class MainForm : Form

    {

        private const uint WDA_NONE = 0;

        private const uint WDA_MONITOR = 1;


        [DllImport("user32.dll")]

        private static extern uint SetWindowDisplayAffinity(IntPtr windowHandle, uint affinity);


        public MainForm()

        {

            InitializeComponent();


            this.onButton.Click  += OnButton_Click;

            this.offButton.Click += OffButton_Click;

        }


        private void OnButton_Click(object sender, EventArgs e)

        {

            this.onButton.BackColor  = Color.White;

            this.offButton.BackColor = Color.Transparent;


            SetWindowDisplayAffinity(this.Handle, WDA_MONITOR);

        }


        private void OffButton_Click(object sender, EventArgs e)

        {

            this.onButton.BackColor  = Color.Transparent;

            this.offButton.BackColor = Color.White;


            SetWindowDisplayAffinity(this.Handle, WDA_NONE);

        }

    }

}



* 캡쳐도구를 이용해 캡쳐방지를 하지 않고 했을 때와  캡쳐방지를 켜고 했을 때 비교

(캡쳐방지를 켠 경우에는 녹화할 때도 검게변한다^^)


반디캠, 칼무리, 캡쳐도구, Print Screen 을 이용해 캡쳐 동작을 취할경우 검은 화면으로 보이게 된다.

메서드 호출시 메서드 안에서 어디에서 호출된 것인지 알고 싶을때가 있다

특히 로그 남길 때 유용하게 쓸수 있다.

아래 코드 처럼 메서드 인자로 [CallerMemberName], [CallerFilePath], [CallerLineNumber] 를 선언해 주면 알아서 내용이 들어가게된다.


using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Windows.Forms;

namespace CompilerServicesTest
{
    public partial class TestForm : Form
    {
        public TestForm()
        {
            InitializeComponent();

            CallMethod();
        }

        private void CallMethod()
        {
            WriteLog("CompilerServices Test!!");
        }

        private void WriteLog(string message,
           [CallerMemberName] string memberName = "",
           [CallerFilePath]   string sourceFilePath = "",
           [CallerLineNumber] int sourceLineNumber = 0)
        {
            Trace.WriteLine("message: " + message);
            Trace.WriteLine("member name: " + memberName);
            Trace.WriteLine("source file path: " + sourceFilePath);
            Trace.WriteLine("source line number: " + sourceLineNumber);
        }
    }
}



참고

https://docs.microsoft.com/ko-kr/dotnet/csharp/language-reference/attributes/caller-information

            using System.Drawing.Text;

            using (InstalledFontCollection fontsCollection = new InstalledFontCollection())
            {
                FontFamily[] fontFamilies = fontsCollection.Families;
                List<string> fonts = new List<string>();
                foreach (FontFamily font in fontFamilies)
                {
                    fonts.Add(font.Name);
                }
             }

cmd 창에서 .net framework 경로로 이동

cd C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319


아래 명령어 실행

aspnet_regiis –i

기억을 위해 남긴다.

간단하게 웹 API 를 작성하고자 할때는 아래처럼 추가한후 Controller 를 추가해주면 된다.



+ Recent posts