最近用VB做外挂,模拟鼠标实现自动化操作。发现驱动级模拟,一直存在问题。今天终于解决了,记录下.
---------------------------------------------------------------------------------
系统环境:win7 64位,VB 32位
winIO环境: 3.0环境
下载地址:@L_502_0@
---------------------------------------------------------------------------------
WinIO是一款免费、开源的系统组件,你可以在@L_502_0@上面免费下载它的
源码。在最新版本3.0中,增加了对64位 Windows操作系统的支持。我就是利用它的功能,
实现了驱动级模拟按键。在我使用的WinIO 3.0中,里面有四个bin 文件,分别是
WinIO32.dll、WinIO64.dll、WinIO32.sys、WinIO64.sys。sys文件是实现核心功能的驱动,
dll文件是封装驱动功能的接口。由于我的系统是64 位系统,使用了VB做界面编程,所以
仅需要 WinIO32.dll和 WinIO64.sys。dll
- VB调试的时候,要把 WinIO32.dll和 WinIO64.sys 文件拷贝到VB安装目录下
- 生成exe文件后,WinIO32.dll和 WinIO64.sys 跟exe文件保持在同目录下即可
- 关于数字签名:
WinIO64.sys没有正式的数字签名,只有测试签名。要使它能成功加载,
必须打开测试模式(cmd里切换到 system32目录再输入 bcdedit /set testsigning on),
然后根据以下步骤信任WinIO64.sys的测试签名:
1.打开 WinIO64.sys的属性框,翻到“数字签名”选项卡,点击“详细信息”
2.在新出来的对话框中点击“查看证书”
3.在又新出来的对话框中点击“安装证书”
4.点击“下一步”,然后选择“将所有的证书放入下列存储”
5.点击浏览,选择“受信任的根证书发布机构”
受信任的根证书发布界面
6.点击“下一步”,然后点击“完成”
7.在弹出的“安全性警告”对话框中选择“是”,才能导入成功
实现方式:
调用:
Private Sub Command6_Click() If InitializeWinIo = False Then '用InitializeWinIo函数加载驱动程序,如果成功会返回true,否则返回false MsgBox "驱动程序加载失败!" Else Dim hwnd As Long hwnd = Shell("Notepad.exe",vbNormalFocus) Sleep 1000 '模拟按下 alt+F 键 MyKeyDownEx VK_MENU Sleep 200 MyKeyDown VK_F MyKeyUp VK_F '模拟按下并释放A键 MyKeyUpEx VK_MENU Sleep 500 '模拟按下 ctl+O 键 MyKeyDownEx VK_Control Sleep 200 MyKeyDown VK_O MyKeyUp VK_O '模拟按下并释放A键 MyKeyUpEx VK_Control ShutdownWinIo '程序结束时记得用ShutdownWinIo函数卸载驱动程序 End If End Sub
模块:
Option Explicit Declare Function MapPhysToLin Lib "WinIo32.dll" (ByVal PhysAddr As Long,ByVal PhysSize As Long,ByRef PhysMemHandle) As Long Declare Function UnmapPhysicalMemory Lib "WinIo32.dll" (ByVal PhysMemHandle,ByVal LinAddr) As Boolean Declare Function GetPhysLong Lib "WinIo32.dll" (ByVal PhysAddr As Long,ByRef PhysVal As Long) As Boolean Declare Function SetPhysLong Lib "WinIo32.dll" (ByVal PhysAddr As Long,ByVal PhysVal As Long) As Boolean Declare Function GetPortVal Lib "WinIo32.dll" (ByVal PortAddr As Integer,ByRef PortVal As Long,ByVal bSize As Byte) As Boolean Declare Function SetPortVal Lib "WinIo32.dll" (ByVal PortAddr As Integer,ByVal PortVal As Long,ByVal bSize As Byte) As Boolean Declare Function InitializeWinIo Lib "WinIo32.dll" () As Boolean Declare Function ShutdownWinIo Lib "WinIo32.dll" () As Boolean Declare Function InstallWinIoDriver Lib "WinIo32.dll" (ByVal DriverPath As String,ByVal Mode As Integer) As Boolean Declare Function RemoveWinIoDriver Lib "WinIo32.dll" () As Boolean Public Const KBC_KEY_CMD = &H64 '键盘命令端口 Public Const KBC_KEY_DATA = &H60 '键盘数据端口 Public Const VK_LButton = &H1 '鼠标左键 Public Const VK_RButton = &H2 '鼠标右键 Public Const VK_Cancel = &H3 'CANCEL键 Public Const VK_MButton = &H4 '鼠标中键 Public Const VK_Back = &H8 '退格键 Public Const VK_Tab = &H9 'TAB键 Public Const VK_Clear = &HC 'CLEAR健 Public Const VK_RETURN = &HD '回车键 Public Const VK_Shift = &H10 'SHIFT键 Public Const VK_Control = &H11 'CTRL键 Public Const VK_MENU = &H12 'MENU键 Public Const VK_Pause = &H13 'PAUSE键 Public Const VK_Capital = &H14 'CAPS LOCK 键 Public Const VK_Escape = &H1B 'ESC键 Public Const VK_Space = &H20 ' 空格键 Public Const VK_PageUp = &H21 'Page Up 键 Public Const VK_PageDown = &H22 'Page Down 键 Public Const VK_End = &H23 'END键 Public Const VK_Home = &H24 'HOME键 Public Const VK_Left = &H25 '光标左键 Public Const VK_Up = &H26 '光标上键 Public Const VK_Right = &H27 '光标右键 Public Const VK_Down = &H28 '光标下键 Public Const VK_Select = &H29 'SELECT键 Public Const VK_Print = &H2A 'Print Screen 键 Public Const VK_Execute = &H2B 'EXECUTE键 Public Const VK_Snapshot = &H2C 'SnapShot键 Public Const VK_Insert = &H2D 'INSERT键 Public Const VK_Delete = &H2E 'DELETE键 Public Const VK_Help = &H2F 'HELP键 Public Const VK_Numlock = &H90 'NUM LOCK 键 Public Const VK_A = &H41 '字母A键 Public Const VK_B = &H42 '字母B键 Public Const VK_C = &H43 '字母C键 Public Const VK_D = &H44 '字母D键 Public Const VK_E = &H45 '字母E键 Public Const VK_F = &H46 '字母F键 Public Const VK_G = &H47 '字母G键 Public Const VK_H = &H48 '字母H键 Public Const VK_I = &H49 '字母I键 Public Const VK_J = &H4A '字母J键 Public Const VK_K = &H4B '字母K键 Public Const VK_L = &H4C '字母L键 Public Const VK_M = &H4D '字母M键 Public Const VK_N = &H4E '字母N键 Public Const VK_O = &H4F '字母O键 Public Const VK_P = &H50 '字母P键 Public Const VK_Q = &H51 '字母Q键 Public Const VK_R = &H52 '字母R键 Public Const VK_S = &H53 '字母S键 Public Const VK_T = &H54 '字母T键 Public Const VK_U = &H55 '字母U键 Public Const VK_V = &H56 '字母V键 Public Const VK_W = &H57 '字母W键 Public Const VK_X = &H58 '字母X键 Public Const VK_Y = &H59 '字母Y键 Public Const VK_Z = &H5A '字母Z键 Public Const VK_0 = &H30 '数字0键 Public Const VK_1 = &H31 '数字1键 Public Const VK_2 = &H32 '数字2键 Public Const VK_3 = &H33 '数字3键 Public Const VK_4 = &H34 '数字4键 Public Const VK_5 = &H35 '数字5键 Public Const VK_6 = &H36 '数字6键 Public Const VK_7 = &H37 '数字7键 Public Const VK_8 = &H38 '数字8键 Public Const VK_9 = &H39 '数字9键 Public Const VK_F1 = &H70 'F1功能键 Public Const VK_F2 = &H71 'F2功能键 Public Const VK_F3 = &H72 'F3功能键 Public Const VK_F4 = &H73 'F4功能键 Public Const VK_F5 = &H74 'F5功能键 Public Const VK_F6 = &H75 'F6功能键 Public Const VK_F7 = &H76 'F7功能键 Public Const VK_F8 = &H77 'F8功能键 Public Const VK_F9 = &H78 'F9功能键 Public Const VK_F10 = &H79 'F10功能键 Public Const VK_F11 = &H7A 'F11功能键 Public Const VK_F12 = &H7B 'F12功能键 Public Const VK_F13 = &H7C 'F13功能键 Public Const VK_F14 = &H7D 'F14功能键 Public Const VK_F15 = &H7E 'F15功能键 Public Const VK_F16 = &H7F 'F16功能键 Public Const VK_Numpad0 = &H60 '小键盘0键 Public Const VK_Numpad1 = &H61 '小键盘1键 Public Const VK_Numpad2 = &H62 '小键盘2键 Public Const VK_Numpad3 = &H63 '小键盘3键 Public Const VK_Numpad4 = &H64 '小键盘4键 Public Const VK_Numpad5 = &H65 '小键盘5键 Public Const VK_Numpad6 = &H66 '小键盘6键 Public Const VK_Numpad7 = &H67 '小键盘7键 Public Const VK_Numpad8 = &H68 '小键盘8键 Public Const VK_Numpad9 = &H69 '小键盘9键 Public Const VK_Multiply = &H6A '小键盘*键 Public Const VK_Add = &H6B '小键盘+键 Public Const VK_Separator = &H6C '小键盘回车键 Public Const VK_Subtract = &H6D '小键盘-键 Public Const VK_Decimal = &H6E '小键盘.键 Public Const VK_Divide = &H6F '小键盘/键 '************************** ' 等待键盘缓冲区为空 '************************** Sub KBCWait4IBE() Dim dwVal As Long Do GetPortVal &H64,dwVal,1 '这句表示从&H64端口读取一个字节并把读出的数据放到变量dwVal中 'GetPortVal函数的用法是GetPortVal 端口号,存放读出数据的变量,读入的长度 Loop While (dwVal And &H2) End Sub '************************************** ' '这个用来模拟按下键,参数vKeyCoad传入按键的虚拟码 ' '************************************** Sub MyKeyDown(ByVal vKeyCoad As Long) ' Dim btScancode As Long btScancode = MapVirtualKey(vKeyCoad,0) KBCWait4IBE '发送数据前应该先等待键盘缓冲区为空 SetPortVal KBC_KEY_CMD,&HD2,1 '发送键盘写入命令 'SetPortVal函数用于向端口写入数据,它的用法是SetPortVal 端口号,欲写入的数据,写入数据的长度 KBCWait4IBE SetPortVal KBC_KEY_DATA,btScancode,1 '写入按键信息,按下键 End Sub '************************************** ' '这个用来模拟释放键,参数vKeyCoad传入按键的虚拟码 ' '************************************** Sub MyKeyUp(ByVal vKeyCoad As Long) ' Dim btScancode As Long btScancode = MapVirtualKey(vKeyCoad,0) KBCWait4IBE '等待键盘缓冲区为空 SetPortVal KBC_KEY_CMD,1 '发送键盘写入命令 KBCWait4IBE SetPortVal KBC_KEY_DATA,(btScancode Or &H80),1 '写入按键信息,释放键 End Sub '********************************************************************* ' 从扩展键转换到普通键,那么普通键的KeyDown事件应该发送两次。 ' 也就是说,如果我想模拟先按下一个扩展键,再按下一个普通键, ' 那么就应该向端口发送 两次 该普通键被按下的信息 ' MyKeyDownEx VK_LEFT '按下左方向键 ' Sleep 200 '延时200毫秒 ' MyKeyUpEx VK_LEFT '释放左方向键 ' Sleep 500 ' MyKeyDown VK_SPACE '按下空格键,注意要发送两次 ' MyKeyDown VK_SPACE ' Sleep 200 ' MyKeyUp VK_SPACE '释放空格键 '********************************************************************** Sub MyKeyDownEx(ByVal vKeyCoad As Long) '模拟扩展键按下,参数vKeyCoad是扩展键的虚拟码 Dim btScancode As Long btScancode = MapVirtualKey(vKeyCoad,1 '发送键盘写入命令 KBCWait4IBE SetPortVal KBC_KEY_DATA,&HE0,1 '写入扩展键标志信息 KBCWait4IBE '等待键盘缓冲区为空 SetPortVal KBC_KEY_CMD,按下键 End Sub '*********************************************** '模拟扩展键弹起 '********************************************** Sub MyKeyUpEx(ByVal vKeyCoad As Long) Dim btScancode As Long btScancode = MapVirtualKey(vKeyCoad,1 '写入扩展键标志信息 KBCWait4IBE '等待键盘缓冲区为空 SetPortVal KBC_KEY_CMD,1 '写入按键信息,释放键 End Sub '---------------------------------------------------------------------------------------------------------------------------------------------------------- Sub MySendKey(bkey As Long) '参数bkey传入要模拟按键的虚拟码即可模拟按下指定键 Dim GInput(0 To 1) As GENERALINPUT Dim KInput As KEYBDINPUT KInput.wVk = bkey '你要模拟的按键 KInput.dwFlags = 0 '按下键标志 GInput(0).dwType = INPUT_KEYBOARD CopyMemory GInput(0).xi(0),KInput,Len(KInput) '这个函数用来把内存中KInput的数据复制到GInput KInput.wVk = bkey KInput.dwFlags = KEYEVENTF_KEYUP ' 释放按键 GInput(1).dwType = INPUT_KEYBOARD ' 表示该消息为键盘消息 CopyMemory GInput(1).xi(0),Len(KInput) '以上工作把按下键和释放键共2条键盘消息加入到GInput数据结构中 SendInput 2,GInput(0),Len(GInput(0)) '把GInput中存放的消息插入到消息列队 End Sub Function MakeKeyLparam(ByVal VirtualKey As Long,ByVal flag As Long) As Long Dim s As String Dim Firstbyte As String 'lparam参数的24-31位 If flag = WM_KEYDOWN Then '如果是按下键 Firstbyte = "00" Else Firstbyte = "C0" '如果是释放键 End If Dim Scancode As Long '获得键的扫描码 Scancode = MapVirtualKey(VirtualKey,0) Dim Secondbyte As String 'lparam参数的16-23位,即虚拟键扫描码 Secondbyte = Right("00" & Hex(Scancode),2) s = Firstbyte & Secondbyte & "0001" '0001为lparam参数的0-15位,即发送次数和其它扩展信息 MakeKeyLparam = Val("&H" & s) End Function
参考链接:
原文链接:https://www.f2er.com/vb/257228.html