성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
[정성태] Modules 창(Ctrl+Shift+U)을 띄워서, 해당 Op...
[정성태] 만드실 수 있습니다. 단지, Unity 엔진 내의 스크립트와 W...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>C# - SendInput Win32 API를 이용한 가상 키보드/마우스</h1> <p> 이 글과 관련된 영상을 유튜브로 제공하고 있습니다. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 닷넷 C# 프로그램 실습 #1 가상 키보드/마우스 (5분 영상) ; <a target='tab' href='https://youtu.be/BDrLENsHbB0'>https://youtu.be/BDrLENsHbB0</a> </pre> <br /> <hr style='width: 50%' /> <br /> 그동안 가상 키보드/마우스 관련해 이미 솔루션을 충분히 다뤄봤는데요,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Raspberry Pi Zero(OTG)를 다른 컴퓨터에 연결해 가상 마우스 + 키보드로 쓰는 방법 (두 번째 이야기) ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/11363'>https://www.sysnet.pe.kr/2/0/11363</a> USB/IP PROJECT를 이용해 C#으로 USB Keyboard + Mouse 가상 장치 만들기 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12229'>https://www.sysnet.pe.kr/2/0/12229</a> </pre> <br /> 그러고 보니, SendInput을 이용한 방법은 한 번도 소개한 적이 없었습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > SendInput ; <a target='tab' href='https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendinput'>https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendinput</a> </pre> <br /> 하지만, 이미 다른 글에서 충분히 잘 다루고 있기 때문에,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Sending Keystrokes to Other Apps with Windows API and C# ; <a target='tab' href='https://dzone.com/articles/sending-keys-other-apps'>https://dzone.com/articles/sending-keys-other-apps</a> inputsimulator/WindowsInput/ ; <a target='tab' href='https://github.com/michaelnoonan/inputsimulator/tree/master/WindowsInput'>https://github.com/michaelnoonan/inputsimulator/tree/master/WindowsInput</a> </pre> <br /> 자세한 설명은 생략하고 다음의 소스 코드만 실어 놓겠습니다. ^^<br /> <br /> <pre style='height: 400px; margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System; using System.Runtime.InteropServices; using System.Threading; namespace ConsoleApp1 { // Sending Keystrokes to Other Apps with Windows API and C# // ; <a target='tab' href='https://dzone.com/articles/sending-keys-other-apps'>https://dzone.com/articles/sending-keys-other-apps</a> // inputsimulator/WindowsInput/ // ; <a target='tab' href='https://github.com/michaelnoonan/inputsimulator/tree/master/WindowsInput'>https://github.com/michaelnoonan/inputsimulator/tree/master/WindowsInput</a> [StructLayout(LayoutKind.Sequential)] internal struct MOUSEINPUT { public int X; public int Y; public uint MouseData; public uint Flags; public uint Time; public IntPtr ExtraInfo; } [StructLayout(LayoutKind.Sequential)] internal struct KEYBDINPUT { public ushort Vk; public ushort Scan; public uint Flags; public uint Time; public IntPtr ExtraInfo; } [StructLayout(LayoutKind.Sequential)] internal struct HARDWAREINPUT { public uint Msg; public ushort ParamL; public ushort ParamH; } [StructLayout(LayoutKind.Explicit)] internal struct MOUSEKEYBDHARDWAREINPUT { [FieldOffset(0)] public HARDWAREINPUT Hardware; [FieldOffset(0)] public KEYBDINPUT Keyboard; [FieldOffset(0)] public MOUSEINPUT Mouse; } [StructLayout(LayoutKind.Sequential)] internal struct INPUT { public uint Type; public MOUSEKEYBDHARDWAREINPUT Data; } class Program { [DllImport("user32.dll", SetLastError = true)] private static extern uint SendInput(uint numberOfInputs, INPUT[] inputs, int sizeOfInputStructure); public static void SendKeyPress(KeyCode keyCode) { INPUT input = new INPUT { Type = 1 }; input.Data.Keyboard = new KEYBDINPUT() { Vk = (ushort)keyCode, Scan = 0, Flags = 0, Time = 0, ExtraInfo = IntPtr.Zero, }; INPUT input2 = new INPUT { Type = 1 }; input2.Data.Keyboard = new KEYBDINPUT() { Vk = (ushort)keyCode, Scan = 0, Flags = 2, Time = 0, ExtraInfo = IntPtr.Zero }; INPUT[] inputs = new INPUT[] { input, input2 }; if (SendInput(2, inputs, Marshal.SizeOf(typeof(INPUT))) == 0) throw new Exception(); } /// <summary> /// Send a key down and hold it down until sendkeyup method is called /// </summary> /// <param name="keyCode"></param> public static void SendKeyDown(KeyCode keyCode) { INPUT input = new INPUT { Type = 1 }; input.Data.Keyboard = new KEYBDINPUT(); input.Data.Keyboard.Vk = (ushort)keyCode; input.Data.Keyboard.Scan = 0; input.Data.Keyboard.Flags = 0; input.Data.Keyboard.Time = 0; input.Data.Keyboard.ExtraInfo = IntPtr.Zero; INPUT[] inputs = new INPUT[] { input }; if (SendInput(1, inputs, Marshal.SizeOf(typeof(INPUT))) == 0) { throw new Exception(); } } /// <summary> /// Release a key that is being hold down /// </summary> /// <param name="keyCode"></param> public static void SendKeyUp(KeyCode keyCode) { INPUT input = new INPUT { Type = 1 }; input.Data.Keyboard = new KEYBDINPUT(); input.Data.Keyboard.Vk = (ushort)keyCode; input.Data.Keyboard.Scan = 0; input.Data.Keyboard.Flags = 2; input.Data.Keyboard.Time = 0; input.Data.Keyboard.ExtraInfo = IntPtr.Zero; INPUT[] inputs = new INPUT[] { input }; if (SendInput(1, inputs, Marshal.SizeOf(typeof(INPUT))) == 0) throw new Exception(); } public enum KeyCode : ushort { #region Media /// <summary> /// Next track if a song is playing /// </summary> MEDIA_NEXT_TRACK = 0xb0, /// <summary> /// Play pause /// </summary> MEDIA_PLAY_PAUSE = 0xb3, /// <summary> /// Previous track /// </summary> MEDIA_PREV_TRACK = 0xb1, /// <summary> /// Stop /// </summary> MEDIA_STOP = 0xb2, #endregion #region math /// <summary>Key "+"</summary> ADD = 0x6b, /// <summary> /// "*" key /// </summary> MULTIPLY = 0x6a, /// <summary> /// "/" key /// </summary> DIVIDE = 0x6f, /// <summary> /// Subtract key "-" /// </summary> SUBTRACT = 0x6d, #endregion #region Browser /// <summary> /// Go Back /// </summary> BROWSER_BACK = 0xa6, /// <summary> /// Favorites /// </summary> BROWSER_FAVORITES = 0xab, /// <summary> /// Forward /// </summary> BROWSER_FORWARD = 0xa7, /// <summary> /// Home /// </summary> BROWSER_HOME = 0xac, /// <summary> /// Refresh /// </summary> BROWSER_REFRESH = 0xa8, /// <summary> /// browser search /// </summary> BROWSER_SEARCH = 170, /// <summary> /// Stop /// </summary> BROWSER_STOP = 0xa9, #endregion #region Numpad numbers /// <summary> /// /// </summary> NUMPAD0 = 0x60, /// <summary> /// /// </summary> NUMPAD1 = 0x61, /// <summary> /// /// </summary> NUMPAD2 = 0x62, /// <summary> /// /// </summary> NUMPAD3 = 0x63, /// <summary> /// /// </summary> NUMPAD4 = 100, /// <summary> /// /// </summary> NUMPAD5 = 0x65, /// <summary> /// /// </summary> NUMPAD6 = 0x66, /// <summary> /// /// </summary> NUMPAD7 = 0x67, /// <summary> /// /// </summary> NUMPAD8 = 0x68, /// <summary> /// /// </summary> NUMPAD9 = 0x69, #endregion #region Fkeys /// <summary> /// F1 /// </summary> F1 = 0x70, /// <summary> /// F10 /// </summary> F10 = 0x79, /// <summary> /// /// </summary> F11 = 0x7a, /// <summary> /// /// </summary> F12 = 0x7b, /// <summary> /// /// </summary> F13 = 0x7c, /// <summary> /// /// </summary> F14 = 0x7d, /// <summary> /// /// </summary> F15 = 0x7e, /// <summary> /// /// </summary> F16 = 0x7f, /// <summary> /// /// </summary> F17 = 0x80, /// <summary> /// /// </summary> F18 = 0x81, /// <summary> /// /// </summary> F19 = 130, /// <summary> /// /// </summary> F2 = 0x71, /// <summary> /// /// </summary> F20 = 0x83, /// <summary> /// /// </summary> F21 = 0x84, /// <summary> /// /// </summary> F22 = 0x85, /// <summary> /// /// </summary> F23 = 0x86, /// <summary> /// /// </summary> F24 = 0x87, /// <summary> /// /// </summary> F3 = 0x72, /// <summary> /// /// </summary> F4 = 0x73, /// <summary> /// /// </summary> F5 = 0x74, /// <summary> /// /// </summary> F6 = 0x75, /// <summary> /// /// </summary> F7 = 0x76, /// <summary> /// /// </summary> F8 = 0x77, /// <summary> /// /// </summary> F9 = 120, #endregion #region Other /// <summary> /// /// </summary> OEM_1 = 0xba, /// <summary> /// /// </summary> OEM_102 = 0xe2, /// <summary> /// /// </summary> OEM_2 = 0xbf, /// <summary> /// /// </summary> OEM_3 = 0xc0, /// <summary> /// /// </summary> OEM_4 = 0xdb, /// <summary> /// /// </summary> OEM_5 = 220, /// <summary> /// /// </summary> OEM_6 = 0xdd, /// <summary> /// /// </summary> OEM_7 = 0xde, /// <summary> /// /// </summary> OEM_8 = 0xdf, /// <summary> /// /// </summary> OEM_CLEAR = 0xfe, /// <summary> /// /// </summary> OEM_COMMA = 0xbc, /// <summary> /// /// </summary> OEM_MINUS = 0xbd, /// <summary> /// /// </summary> OEM_PERIOD = 190, /// <summary> /// /// </summary> OEM_PLUS = 0xbb, #endregion #region KEYS /// <summary> /// /// </summary> KEY_0 = 0x30, /// <summary> /// /// </summary> KEY_1 = 0x31, /// <summary> /// /// </summary> KEY_2 = 50, /// <summary> /// /// </summary> KEY_3 = 0x33, /// <summary> /// /// </summary> KEY_4 = 0x34, /// <summary> /// /// </summary> KEY_5 = 0x35, /// <summary> /// /// </summary> KEY_6 = 0x36, /// <summary> /// /// </summary> KEY_7 = 0x37, /// <summary> /// /// </summary> KEY_8 = 0x38, /// <summary> /// /// </summary> KEY_9 = 0x39, /// <summary> /// /// </summary> KEY_A = 0x41, /// <summary> /// /// </summary> KEY_B = 0x42, /// <summary> /// /// </summary> KEY_C = 0x43, /// <summary> /// /// </summary> KEY_D = 0x44, /// <summary> /// /// </summary> KEY_E = 0x45, /// <summary> /// /// </summary> KEY_F = 70, /// <summary> /// /// </summary> KEY_G = 0x47, /// <summary> /// /// </summary> KEY_H = 0x48, /// <summary> /// /// </summary> KEY_I = 0x49, /// <summary> /// /// </summary> KEY_J = 0x4a, /// <summary> /// /// </summary> KEY_K = 0x4b, /// <summary> /// /// </summary> KEY_L = 0x4c, /// <summary> /// /// </summary> KEY_M = 0x4d, /// <summary> /// /// </summary> KEY_N = 0x4e, /// <summary> /// /// </summary> KEY_O = 0x4f, /// <summary> /// /// </summary> KEY_P = 80, /// <summary> /// /// </summary> KEY_Q = 0x51, /// <summary> /// /// </summary> KEY_R = 0x52, /// <summary> /// /// </summary> KEY_S = 0x53, /// <summary> /// /// </summary> KEY_T = 0x54, /// <summary> /// /// </summary> KEY_U = 0x55, /// <summary> /// /// </summary> KEY_V = 0x56, /// <summary> /// /// </summary> KEY_W = 0x57, /// <summary> /// /// </summary> KEY_X = 0x58, /// <summary> /// /// </summary> KEY_Y = 0x59, /// <summary> /// /// </summary> KEY_Z = 90, #endregion #region volume /// <summary> /// Decrese volume /// </summary> VOLUME_DOWN = 0xae, /// <summary> /// Mute volume /// </summary> VOLUME_MUTE = 0xad, /// <summary> /// Increase volue /// </summary> VOLUME_UP = 0xaf, #endregion /// <summary> /// Take snapshot of the screen and place it on the clipboard /// </summary> SNAPSHOT = 0x2c, /// <summary>Send right click from keyboard "key that is 2 keys to the right of space bar"</summary> RightClick = 0x5d, /// <summary> /// Go Back or delete /// </summary> BACKSPACE = 8, /// <summary> /// Control + Break "When debuging if you step into an infinite loop this will stop debug" /// </summary> CANCEL = 3, /// <summary> /// Caps lock key to send cappital letters /// </summary> CAPS_LOCK = 20, /// <summary> /// Ctlr key /// </summary> CONTROL = 0x11, /// <summary> /// Alt key /// </summary> ALT = 18, /// <summary> /// "." key /// </summary> DECIMAL = 110, /// <summary> /// Delete Key /// </summary> DELETE = 0x2e, /// <summary> /// Arrow down key /// </summary> DOWN = 40, /// <summary> /// End key /// </summary> END = 0x23, /// <summary> /// Escape key /// </summary> ESC = 0x1b, /// <summary> /// Home key /// </summary> HOME = 0x24, /// <summary> /// Insert key /// </summary> INSERT = 0x2d, /// <summary> /// Open my computer /// </summary> LAUNCH_APP1 = 0xb6, /// <summary> /// Open calculator /// </summary> LAUNCH_APP2 = 0xb7, /// <summary> /// Open default email in my case outlook /// </summary> LAUNCH_MAIL = 180, /// <summary> /// Opend default media player (itunes, winmediaplayer, etc) /// </summary> LAUNCH_MEDIA_SELECT = 0xb5, /// <summary> /// Left control /// </summary> LCONTROL = 0xa2, /// <summary> /// Left arrow /// </summary> LEFT = 0x25, /// <summary> /// Left shift /// </summary> LSHIFT = 160, /// <summary> /// left windows key /// </summary> LWIN = 0x5b, /// <summary> /// Next "page down" /// </summary> PAGEDOWN = 0x22, /// <summary> /// Num lock to enable typing numbers /// </summary> NUMLOCK = 0x90, /// <summary> /// Page up key /// </summary> PAGE_UP = 0x21, /// <summary> /// Right control /// </summary> RCONTROL = 0xa3, /// <summary> /// Return key /// </summary> ENTER = 13, /// <summary> /// Right arrow key /// </summary> RIGHT = 0x27, /// <summary> /// Right shift /// </summary> RSHIFT = 0xa1, /// <summary> /// Right windows key /// </summary> RWIN = 0x5c, /// <summary> /// Shift key /// </summary> SHIFT = 0x10, /// <summary> /// Space back key /// </summary> SPACE_BAR = 0x20, /// <summary> /// Tab key /// </summary> TAB = 9, /// <summary> /// Up arrow key /// </summary> UP = 0x26, } } } </pre> <br /> 저렇게 SendInput 관련 코드를 작성했으면 이제 키보드 입력 전달을 다음과 같이 할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > static void Main(string[] args) { Thread.Sleep(5 * 1000); <span style='color: blue; font-weight: bold'>SendKeyPress(KeyCode.KEY_Z);</span> } </pre> <br /> (<a target='tab' href='https://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=1689&boardid=331301885'>첨부 파일은 이 글의 예제 코드를 포함</a>합니다.)<br /> <br /> 사실 보안 도구와 잘 협업하고 있는 게임과 같은 특수 사례만 아니라면 SendInput API만으로도 대부분의 키보드/마우스 입력을 전달하는데 별문제가 없습니다.<br /> <br /> <hr style='width: 50%' /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 파이썬 키보드 마우스 제어하기 (pyautogui) ; <a target='tab' href='https://blog.naver.com/cjinnnn/223048792430'>https://blog.naver.com/cjinnnn/223048792430</a> </pre> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1144
(왼쪽의 숫자를 입력해야 합니다.)