首页 > 系统相关 >用C#调用Windows API向指定窗口发送按键消息

用C#调用Windows API向指定窗口发送按键消息

时间:2023-03-30 22:15:51浏览次数:58  
标签:IntPtr 窗口 C# DllImport private Windows int API static

用C#调用Windows API向指定窗口发送

一、调用Windows API。
 C#下调用Windows API方法如下:
 1、引入命名空间:using System.Runtime.InteropServices;
 2、引用需要使用的方法,格式:[DllImport("DLL文件")]方法的声明;
 [DllImport("user32.dll")]private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
 [DllImport("user32.dll")]private static extern bool SetForegroundWindow(IntPtr hWnd);
 [DllImport("user32.dll")]private static extern IntPtr FindWindow(string lpClassName,string lpWindowName);
 [DllImport("user32.dll")]private static extern int SendMessage(IntPtr hWnd,int Msg,int wParam,int lParam);
 [DllImport("user32.dll")]private static extern bool SetCursorPos(int X, int Y);
 [DllImport("user32.dll")]private static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
 [DllImport("user32.dll")]private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
  [DllImport("user32.dll")]private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndlnsertAfter, int X, int Y, int cx, int cy, uint Flags);
 //ShowWindow参数
 private const int SW_SHOWNORMAL = 1;
 private const int SW_RESTORE = 9;
 private const int SW_SHOWNOACTIVATE = 4;
 //SendMessage参数
 private const int WM_KEYDOWN = 0X100;
 private const int WM_KEYUP = 0X101;
 private const int WM_SYSCHAR = 0X106;
 private const int WM_SYSKEYUP = 0X105;
 private const int WM_SYSKEYDOWN = 0X104;
 private const int WM_CHAR = 0X102;

二、找到目标窗口
1)、根据窗口的标题得到句柄
 IntPtr myIntPtr = FindWindow(null,"窗口名"); //null为类名,可以用Spy++得到,也可以为空
 ShowWindow(myIntPtr, SW_RESTORE); //将窗口还原
 SetForegroundWindow(myIntPtr); //如果没有ShowWindow,此方法不能设置最小化的窗口
2)、遍历所有窗口得到句柄
1 定义委托方法CallBack,枚举窗口API(EnumWindows),得到窗口名API(GetWindowTextW)和得到窗口类名API(GetClassNameW)
 public delegate bool CallBack(int hwnd, int lParam);
 [DllImport("user32")]public static extern int EnumWindows(CallBack x, int y);
  [DllImport("user32.dll")]private static extern int GetWindowTextW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)]StringBuilder lpString, int nMaxCount);
 [DllImport("user32.dll")]private static extern int GetClassNameW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)]StringBuilder lpString, int nMaxCount);
2 调用EnumWindows遍历窗口
 CallBack myCallBack = new CallBack(Recall);
 EnumWindows(myCallBack, 0);
3 回调方法Recall
 public bool Recall(int hwnd, int lParam)
 {
  StringBuilder sb = new StringBuilder(256);
  IntPtr PW = new IntPtr(hwnd);

  GetWindowTextW(PW,sb,sb.Capacity); //得到窗口名并保存在strName中
  string strName = sb.ToString();

  GetClassNameW(PW,sb,sb.Capacity); //得到窗口类名并保存在strClass中
  string strClass = sb.ToString();

  if (strName.IndexOf("窗口名关键字") >= 0 && strClass.IndexOf("类名关键字") >= 0)
  {
   return false; //返回false中止EnumWindows遍历
  }
  else
  {
   return true; //返回true继续EnumWindows遍历
  }
 }
3)、打开窗口得到句柄
1 定义设置活动窗口API(SetActiveWindow),设置前台窗口API(SetForegroundWindow)
 [DllImport("user32.dll")]static extern IntPtr SetActiveWindow(IntPtr hWnd);
 [DllImport("user32.dll")][return: MarshalAs(UnmanagedType.Bool)]static extern bool SetForegroundWindow(IntPtr hWnd);
2 打开窗口
 Process proc = Process.Start(@"目标程序路径");
 SetActiveWindow(proc.MainWindowHandle);
 SetForegroundWindow(proc.MainWindowHandle);

三、向指定的窗口输入数据
1 利用发送消息API(SendMessage)向窗口发送数据
 InputStr(myIntPtr, _GameID); //输入游戏ID
 SendMessage(myIntPtr, WM_SYSKEYDOWN, 0X09, 0); //输入TAB(0x09)
 SendMessage(myIntPtr, WM_SYSKEYUP, 0X09, 0);
 InputStr(myIntPtr, _GamePass); //输入游戏密码
 SendMessage(myIntPtr, WM_SYSKEYDOWN, 0X0D, 0); //输入ENTER(0x0d)
 SendMessage(myIntPtr, WM_SYSKEYUP, 0X0D, 0);

 /// <summary>
 /// 发送一个字符串
 /// </summary>
 /// <param name="myIntPtr">窗口句柄</param>
 /// <param name="Input">字符串</param>
 public void InputStr(IntPtr myIntPtr, string Input)
 {
  byte[] ch = (ASCIIEncoding.ASCII.GetBytes(Input));
  for (int i = 0; i < ch.Length; i++)
  {
   SendMessage(PW, WM_CHAR, ch, 0);
  }
 }
2 利用鼠标和键盘模拟向窗口发送数据
 SetWindowPos(PW, (IntPtr)(-1), 0, 0, 0, 0, 0x0040 | 0x0001); //设置窗口位置
 SetCursorPos(476, 177); //设置鼠标位置
 mouse_event(0x0002, 0, 0, 0, 0); //模拟鼠标按下操作
 mouse_event(0x0004, 0, 0, 0, 0); //模拟鼠标放开操作
 SendKeys.Send(_GameID);   //模拟键盘输入游戏ID
 SendKeys.Send("{TAB}"); //模拟键盘输入TAB
 SendKeys.Send(_GamePass); //模拟键盘输入游戏密码
 SendKeys.Send("{ENTER}"); //模拟键盘输入ENTER

标签:IntPtr,窗口,C#,DllImport,private,Windows,int,API,static
From: https://www.cnblogs.com/lidabo/p/17274511.html

相关文章

  • 「解题报告」ARC122E Increasing LCMs
    紫题不会了,感觉要退役了前缀\(\mathrm{lcm}\)的限制很强,考虑每次消去一个数。发现最后一个数没有依赖,考虑最后一个数的条件,其实就是最后一个数不是前\(n-1\)个数的\(\mathrm{lcm}\)的倍数,即\(\displaystyle\gcd(\mathop{\mathrm{lcm}}_{i\nej}(a_j),a_i)<a_i\)。这......
  • react useComparedState
    import{useCallback,useRef,useState}from'react';import{shallowEqual}from"../utils/shallowEqual";functionuseComparedState(initialState:any){const[state,setState]=useState(initialState);conststateRef=useRef......
  • centos8重启网络服务
    1.重启网卡之前一定要重新载入一下配置文件,不然不能立即生效nmclicreload2.重启网卡(下面的三条命令都可以):nmclicupens160nmclidreapplyens160nmclidconnectens160备注:ens160是网卡名字......
  • Surge for Mac配置本地代理监听端口
    1setting-general  2advancedproxyservicesettings  3这里修改代理监听的端口  4不同的网站和不同的app都代理的话,需要根据监听协议修改跟surge的监听协议和端口一致,就可以通过代理来访问了,比如chrome的代理插件switchyOmega ......
  • Oracle PL/SQL 自治事务
    自治事务是PL/SQL静态SQL的一个特性,可声明于存储过程、函数或触发器中。它是和主事务分开的事务,可以独立执行事务,不与主事务共享锁、资源,不受主事务提交的影响。自治事务可以用来记录日志,记录计数值,而不受主事务回滚的影响。--创建自治事务的存储过程createorreplaceprocedur......
  • vue3+vite+ts 配置@时vscode报找不到__dirname的问题
    vue3+vite+ts配置@时vscode报找不到__dirname的问题-CSDN博客  原因:path模块是node.js的内置模块,而node.js默认不支持ts文件的解决:安装@type/node依赖包 npminstall@types/node--save-dev......
  • 使用 Oracle LogMiner 分析重做日志
    概述我们知道oracle的redo和归档日志,记录了数据库的事务的相关信息。在日常的数据库管理过程中,我们有时需要,查看特定时刻特定用户在数据库上执行的操作。这时我们可以通过用logminer分析日志文件获取相关信息。logminer分析归档日志文件所获得的信息并不是原始的操作信息,而是等......
  • MSF实战免杀过静态:ShellCode加花指令
    分析MSF的ShellCode1.Hash寻找系统API函数由于ShellCode是没有PE结构的,无法通过导入表来调用系统的API函数,因此,这部分是一个通用的API调用函数,它可以根据给定的哈希值查找并调用相应的API。在查找API时,它会遍历已加载模块的列表以及每个模块的导出地址表。这个函数在Shellcode中......
  • 2023-03-30-链栈LinkStack的实现
    1#include<stdio.h>2#include<malloc.h>34typedefstructSNode5{6intdata;7structSNode*next;8}SNode,*LinkStack;9//栈的主要操作是在栈顶进行插入和删除,所以将链表的头部看为栈顶最合适10voidinitLinkStack(LinkStackS)//初始化1......
  • 攻防世界-catcat-new
    一道有关任意文件读取,Linux敏感文件,flask-session伪造的题目 一、基础知识(参考链接)/etc/passwd该文件储存了该Linux系统中所有用户的一些基本信息,只有root权限才可以修改。其具体格式为   用户名:口令:用户标识号:组标识号:注释性描述:主目录:登录Shell(以冒号作为......