💬 C# WinForms + AutoHotkey를 활용한 카카오톡 메시지 자동 입력 예제

HJSOFT 조회 1

🔧 참고한 자료 엑셀 카카오톡 자동화프로그램만들기(윈도우API응용) - 오빠두엑셀 : 강의 인상적으로 봤습니다 감사합니다.​AutoHotkey와 Excel을 연동하여 구현한 예제를 보고 VB소스를 > C# WinForm으로 직접 구현해보는 실습을 해봤습니다. + 키인 방식 변경과 첨부파일​⚖️ 법적 주의카카오톡은 카카오의 서비스 및 프로그램 자산입니다.비…

🔧 참고한 자료

엑셀 카카오톡 자동화프로그램만들기(윈도우API응용) - 오빠두엑셀 : 강의 인상적으로 봤습니다 감사합니다.

AutoHotkey와 Excel을 연동하여 구현한 예제를 보고

VB소스를 > C# WinForm으로 직접 구현해보는 실습을 해봤습니다. + 키인 방식 변경과 첨부파일

⚖️ 법적 주의

  • 카카오톡은 카카오의 서비스 및 프로그램 자산입니다.

  • 비정상적인 자동화 또는 대량 메시지 전송은 서비스 약관 위반 및 계정 제재를 초래할 수 있습니다.

  • 본 글은 기술 학습 및 테스트용 예제이며, 실제로 자동화 기능을 사용하는 것은 카카오의 정책을 반드시 확인하고 이용하셔야 합니다.

※ 본 게시물은 비상업적 목적의 기술 공유입니다.

오직 개인 학습과 테스트를 위한 코드입니다.


🛠️ 개발환경

  • C# .NET WinForm (.NET Framework 4.7 이상)

  • AutoHotkey.Interop (NuGet 패키지 설치 또는 직접 DLL 참조)

  • Windows 10/11

  • 카카오톡 PC 버전


using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Runtime.InteropServices; using System.Threading; using AutoHotkey.Interop; namespace KakaoTalkAutomation { public partial class Form1 : Form { #region Win32 API Declarations [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, string lParam); [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern int PostMessage(IntPtr hwnd, int wMsg, int wParam, int lParam); [DllImport("user32.dll")] private static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo); [DllImport("user32.dll")] private static extern short GetKeyState(int nVirtKey); [DllImport("user32.dll")] private static extern IntPtr GetWindow(IntPtr hwnd, int wCmd); [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern int GetClassName(IntPtr hwnd, System.Text.StringBuilder lpClassName, int nMaxCount); [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern int GetWindowText(IntPtr hwnd, System.Text.StringBuilder lpString, int nMaxCount); #endregion #region Constants private const int WM_SETTEXT = 0x000C; private const int WM_KEYDOWN = 0x0100; private const int WM_KEYUP = 0x0101; private const int VK_RETURN = 0x0D; private const int VK_CONTROL = 0x11; private const int VK_ESC = 0x1B; private const int KEYEVENTF_KEYUP = 0x0002; private const int VK_A = 0x41; private const int VK_V = 0x56; private const int VK_C = 0x43; private const int VK_DOWN = 0x28; private const int VK_UP = 0x26; [DllImport("user32.dll")] static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll")] static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, UIntPtr dwExtraInfo); const uint MOUSEEVENTF_LEFTDOWN = 0x0002; const uint MOUSEEVENTF_LEFTUP = 0x0004; [DllImport("user32.dll")] static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); [DllImport("user32.dll")] static extern bool SetCursorPos(int X, int Y); [DllImport("user32.dll")] static extern bool DestroyWindow(IntPtr hWnd); [StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left; public int Top; public int Right; public int Bottom; } #endregion private AutoHotkeyEngine ahk; private void Form1_Load(object sender, EventArgs e) { ahk = new AutoHotkeyEngine(); // AutoHotkey 인터프리터 초기화 } /// <summary> /// 카카오톡 메시지를 보내는 메인 메서드 /// </summary> public bool SendKakao(string target, string message, bool chatRoomSearch = false, int delay = 1) { IntPtr hwndRichEdit = FindRecepientHwnd(target, chatRoomSearch, delay); if (hwndRichEdit == IntPtr.Zero) { MessageBox.Show("Could not find the KakaoTalk chat window for the target."); //Could not find the KakaoTalk chat window for the target. return false; } SendTextMessage(message, hwndRichEdit); return true; } //실제 메시지 전송을 처리하는 메서드 private void SendTextMessage(string message, IntPtr hwndRichEdit) { // 텍스트에 줄바꿈이 있으면 Shift + Enter로 변경 string input = message.Replace("\r\n", "+{Enter}").Replace("\n", "+{Enter}"); //textBox1.Text 대화창명 = 메세지 보낼사람 string script = $@" SetTitleMatchMode, 2 IfWinExist, {textBox1.Text} {{ WinActivate Sleep, 500 SendInput, {input} ; SendInput 사용 Send, {{Enter}} ; 엔터 전송 }}"; ahk.ExecRaw(script); // AutoHotkey 스크립트 실행 }
// 수신자의 채팅창 핸들을 찾는 메서드 private IntPtr FindRecepientHwnd(string target, bool chatRoomSearch, int delay) { ActiveChat(target, delay, chatRoomSearch); IntPtr hwndKakaoTalk = FindWindow(null, target); DateTime startTime = DateTime.Now; while (hwndKakaoTalk == IntPtr.Zero) { hwndKakaoTalk = FindWindow(null, target); if ((DateTime.Now - startTime).TotalSeconds > 2) { return IntPtr.Zero; } Thread.Sleep(100); } IntPtr hwndRichEdit = FindWindowEx(hwndKakaoTalk, IntPtr.Zero, "RICHEDIT50W", null); //RICHEDIT50W if (hwndRichEdit == IntPtr.Zero) { hwndRichEdit = FindWindowEx(hwndKakaoTalk, IntPtr.Zero, "RichEdit20W", null); } return hwndRichEdit; } // 채팅창을 활성화하는 메서드 private void ActiveChat(string target, int delay, bool chatRoomSearch) { if (FindWindow(null, target) != IntPtr.Zero) { return; } IntPtr hwndMain = FindHwndEVA(); if (hwndMain == IntPtr.Zero) { return; } IntPtr hwndChild1 = FindWindowEx(hwndMain, IntPtr.Zero, "EVA_ChildWindow", null); IntPtr hwndChild2 = FindWindowEx(hwndChild1, IntPtr.Zero, "EVA_Window", null); if (chatRoomSearch) { hwndChild2 = FindWindowEx(hwndChild1, hwndChild2, "EVA_Window", null); } IntPtr hwndEdit = FindWindowEx(hwndChild2, IntPtr.Zero, "Edit", null); SendMessage(hwndEdit, WM_SETTEXT, 0, target); Thread.Sleep(delay); if (chatRoomSearch) { PostMessage(hwndEdit, WM_KEYDOWN, VK_UP, 0); Thread.Sleep(delay); } PostMessage(hwndEdit, WM_KEYDOWN, VK_RETURN, 0); Thread.Sleep(delay); } // 카카오톡 메인 윈도우를 찾는 메서드 private IntPtr FindHwndEVA() { IntPtr hwnd = FindWindowEx(IntPtr.Zero, IntPtr.Zero, null, null); StringBuilder className = new StringBuilder(100); StringBuilder windowText = new StringBuilder(100); while (hwnd != IntPtr.Zero) { GetClassName(hwnd, className, 100); if (className.ToString().Contains("EVA_Window_Dblclk")) { GetWindowText(hwnd, windowText, 100); if (windowText.ToString().Contains("카카오톡") || windowText.ToString().Contains("KakaoTalk")) { return hwnd; } } hwnd = FindWindowEx(IntPtr.Zero, hwnd, null, null); } return IntPtr.Zero; } // Ctrl 키 상태를 확인하는 메서드 private bool IsCtrlKeyDown() { const int KEY_MASK = 0xFF80; return (GetKeyState(VK_CONTROL) & KEY_MASK) != 0; } private void button1_Click(object sender, EventArgs e) { SendKakao(textBox1.Text, textBoxErrorTExt1.Text); }

첨부파일일경우

string filePath = @"C:\Users\YourName\Desktop\test.png"; // 첨부할 파일 경로

string script = $@"

SetTitleMatchMode, 2

IfWinExist, {카카오톡=대화창명이름}

{{

WinActivate

Sleep, 300

file := ""{filePath}""

if FileExist(file)

{{

; 파일 드래그처럼 마우스로 붙여넣기 시뮬레이션

Clipboard := """" ; 클립보드 초기화

Clipboard := file

ClipWait, 1

Send, ^v ; Ctrl+V로 파일 첨부

Sleep, 500

Send, {{Enter}} ; 전송

}}

else

{{

MsgBox, File not found: {filePath}

}}

}}";

ahk.ExecRaw(script);

댓글 0

첫 댓글을 남겨보세요.