如何在所有应用程序中模拟键盘输入?

9
我正在编写一个应用程序(使用C#语言),其中的一部分需要模拟并发送一些按键到另一个应用程序中。我使用了http://inputsimulator.codeplex.com/项目来模拟按键,它在许多应用程序中都起作用,但在某些应用程序中却不起作用,例如《格斗之王4》。
我已经通过谷歌搜索得知,有许多答案,从“这是不可能的”到“你必须使用XXX库”等等。那些回答吓坏了我,甚至几乎让我相信当时我无法完成任务,但是...
微软虚拟键盘可以胜任。它在所有应用程序中都能正常工作。所以这是可以实现的... 你们聪明的家伙中,有没有人知道我该如何做到这一点?

你到目前为止实际上尝试了哪些代码? - MethodMan
我正在使用上面提到的项目。那里最低的方法是[DllImport("user32.dll", SetLastError = true)] internal static extern UInt32 SendInput(UInt32 numberOfInputs, InputMsg[] inputs, Int32 sizeOfInputStructure);在许多应用程序中它运行得非常完美,但不是所有的应用程序都可以。 :/ - Fenix Voltres
4
@FenixVoltres:我对Windows屏幕键盘进行了反向工程,并发现它使用与您链接的库相同的输入方法(SendInput)。我挂钩了所有我能想到的与键盘相关的函数(keybd_eventSendInputSetKeyboardState等),但唯一被调用的函数是SendInput)。请尝试将该库的代码与MSDN文档进行双重检查。 - Neal P
1
起初,我打算拆解OSK并挂钩所有与键盘相关的函数;但后来我决定使用API Monitor(http://www.rohitab.com/apimonitor)来监视程序执行,因为只有少数几个函数能够以这种方式产生输入。你应该记录上述函数以及与扫描码相关的任何函数(它们应该属于同一类别)。 - Neal P
非常感谢您提供有关此工具的信息,它非常有用,并帮助我解决了问题 - 更多信息请参见我的下面的答案。 - Fenix Voltres
显示剩余2条评论
3个回答

6

好的,我想我终于让它工作了。我使用了由Neal P推荐的API Monitor,并且它显示了OSK调用和我的调用之间只有很小的差异。稍后,我尝试在发送按下和释放键的消息之间使我的调用线程休眠一段时间,然后就可以了。


如果有其他人尝试使用API监视器,它只会显示INPUT数组中的第一个数组项,即如果您将包含4个项目的数组传递给SendItem(例如,当OSK关闭以模拟LWIN按下、U按下、U松开和LWIN松开时),则需要能够在参数窗口中看到整个数组。要查看整个数组,请编辑安装API监视器的"\API\Windows"目录中的User32.xml文件,并将<Param Type="LPINPUT" Name="pInputs" />更改为<Param Type="LPINPUT" Name="pInputs" Count="nInputs" />。 - Julius
你是怎么让它工作的?我也在尝试解决同样的问题,但仅仅让线程睡眠一段时间并不能真正解决任何问题。InputSimulator.SimulateKeyDown(VirtualKeyCode.VK_0); System.Threading.Thread.Sleep(1000); InputSimulator.SimulateKeyUp(VirtualKeyCode.VK_0); - Bogdan Molinger
@BogdanMolinger 的评论有任何新进展吗? - MMM

1

虽然您已经达到了目的,但是您实现它的方式并没有根本性地回答您的问题:如何在所有应用程序中模拟键盘输入?

有许多情况下,常见的用户模式Microsoft API已经无法使用,例如使用DirectInput API或受保护游戏的游戏应用程序。

我已经构建了一个,可以帮助解决这些问题,它提供了一个简单的C API,内部与设备过滤驱动程序通信。它能够发送基于DirectInput的游戏输入,并且还能够绕过一些游戏保护。我已经检查过,它仍然能够通过使用x64版本的库绕过一些已知的游戏保护。游戏保护通常只钩住x86系统的API。好吧,至少现在,也就是2012年2月18日,这就是我看到的情况。


没错,DirectInput让我头痛得要命。我不得不暂停我的应用程序开发一段时间,但我肯定会在接下来的几天里查看您的库,因为它似乎是我一直在寻找的东西。 - Fenix Voltres
@FenixVoltres,目前我只支持纯C API,但有用户在github上贡献了一个C#项目,使用P/Invoke调用它,你可以在这里查看:https://github.com/candera/kchordr/blob/master/Program.cs - oblitum

0

2
我尝试了一下,但是出现了相同的情况 - SendKeys.Send(string) 能够工作,但并非在每个应用程序中都能正常工作。记事本或资源管理器可以正确处理它,但我无法让它在任何全屏游戏中工作。 - Fenix Voltres
大多数较新的在线游戏都非常努力地防止人们编写“机器人”程序,因此它比将按键发送到记事本要困难一些。您仍然可以通过使用低级Win32.dll API调用来绕过其中一些努力,但这当然会使您面临责任,具体取决于您居住的地区,所以我将研究留给您自己去解决。 - Bueller
如果那些方法不是我使用的方法,你能不能多说几句?实际上,这个项目是我在波兰克拉科夫AGH科技大学本科毕业设计的一部分,我不想违法。 :P 顺便说一下,在我的情况下做一个虚拟键盘(或者说一种新的计算机输入方法)是完全合法的,我认为是这样的吧? - Fenix Voltres

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接