在远程桌面上运行时替代 SendKeys?

Posted

技术标签:

【中文标题】在远程桌面上运行时替代 SendKeys?【英文标题】:Alternative to SendKeys when running over Remote Desktop? 【发布时间】:2009-07-16 16:00:15 【问题描述】:

我有一个应用程序,它通过 SendKeys 将击键注入应用程序。

很遗憾,当我通过远程桌面运行该应用程序时,它无法运行 因为众所周知的问题是 SendKeys 不适用于远程桌面。

以前有没有人解决过这个问题,或者对如何解决它有什么好的建议?

【问题讨论】:

我找到了解决此问题的方法,即使用 AutoIT 脚本将密钥发送到 RDP 窗口。 【参考方案1】:

SendKeys 不适合主要是因为:

它只能将密钥发送到活动/焦点应用程序,这永远不能保证工作,因为活动应用程序可能会在实际发送密钥的时间之间发生变化。 RDP 和许多其他库(例如 DirectX)主要出于安全原因阻止它们。

更好的选择:

使用SendMessageSendInput 满足简单需求 可以找到一些关于如何使用 SendMessage 的好例子: Send strings to another application by using Windows messages SendMessage via pInvoke How To Send Keystrokes To Extern Win Application 更精细的需求,建议使用WCF 要开始使用,请阅读此 Basic Tutorial,其中讨论了进程间通信

使用SendMessage的示例代码:

HWND hwndNotepad = FindWindow(_T("Notepad"), NULL);
HWND hwndEdit = FindWindowEx(hwndNotepad, NULL, _T("Edit"), NULL);
SendMessage(hwndEdit, WM_SETTEXT, NULL, (LPARAM)_T("hello"));

【讨论】:

对于添加了安全选项的 RDP 会话,您模拟用户输入的唯一两种方法是编写驱动程序 (msdn.microsoft.com/en-us/library/windows/hardware/…),这对 C# 开发人员来说很麻烦,或者使用可以完美运行的 SendInput!我建议使用库inputsimulator.codeplex.com 但要注意使用 InputSimulator.SimulateTextEntry("text");而不是 InputSimulator.SimulateKeyDown(VirtualKeyCode.VK_B);【参考方案2】:

在我的例子中,我成功地将 WinAPI 的 SendInput 与硬件扫描代码一起使用。 SendKeys 似乎错误地将字符映射到扫描代码。

【讨论】:

+1 如果使用具有增强安全性的 RDP(禁用键盘等),这是最短且正确的答案。我推荐这个库:inputsimulator.codeplex.com 但要注意使用 InputSimulator.SimulateTextEntry("text");而不是 InputSimulator.SimulateKeyDown(VirtualKeyCode.VK_B);【参考方案3】:

您可以通过让桌面在使用前始终登录(或配置为每次启动时自动登录)来解决 RDP 问题。

即使使用自动登录,如果您需要远程桌面访问来运行自动化或管理系统等,首选方法是使用 VNC 而不是 RDP 进行远程访问。原因是 VNC 是跨平台的,您不会遇到此 RDP 问题。 VNC 就像您的实际桌面(RDP 控制台会话 0 或机器的“头”)的中继一样工作,缺点是一次只能进行一个远程会话(或者你们都共享同一个桌面 + 键盘 + 鼠标)。 VNC 也适用于虚拟机。使用 VNC 代替 RDP 或来自 (VMWare/Hyper-V/Xen) 虚拟机管理器软件的本地 (RDP) 访问。

使用 VNC 唯一需要注意的是,桌面未配置为在空闲或屏幕保护程序时自动锁定,这也可能会停止发送键和 GUI 自动化运行,因此请务必禁用它。屏幕保护和显示器省电都可以,只是没有自动锁定和密码保护。

注意:我不确定,但相信由于 VNC“按原样”中继桌面,从应用程序/系统的角度来看,它与在本地执行相同,因此理论上它也应该能够欺骗不允许通过 RDP 发送密钥的系统/应用程序。我对 AutoIt + SendKeys 使用此 VNC 方法没有任何问题,无论我是通过 VNC 主动连接还是断开连接(断开连接后 sendkeys/automation 仍然继续工作,因为在实际桌面上,它仍然登录,只是 VNC 没有活跃)。

【讨论】:

有趣,感谢您的信息。你有什么特别推荐的 VNC 软件吗?最好是开源的。 对不起,除了 Windows 不能推荐太多,我只在 Windows 上使用过 VNC 服务器和客户端。在 Windows 上,RealVNC 和 TightVNC 运行良好,不记得是否是 OSS,但它们有免费和商业版本。我只用免费的。免费的唯一限制通常是关于加密安全级别。但是,如果您在 *** 或公司网络中工作,这通常不是一个问题。【参考方案4】:

在我的例子中,我使用 sendkeys 作为测试自动化的一部分。它不适用于我的构建机器,构建代理通过远程桌面协议运行。我对此并不满意,但作为我的自动化构建的一部分,我能够跳过该测试。

使用 Win32 调用发送窗口消息可能会奏效,如果我有时间我可能会在某天尝试。

无论如何,这里是检查当前代码是否在远程桌面会话中运行:

System.Environment.GetEnvironmentVariable("SESSIONNAME").StartsWith("RDP-")

【讨论】:

以上是关于在远程桌面上运行时替代 SendKeys?的主要内容,如果未能解决你的问题,请参考以下文章

win7系统遇到远程桌面超出了最大允许连接数的问题如何解决

怎样使用windows 7自带的远程桌面连接

远程桌面断开连接时 GetForegroundWindow 返回 Null

windows server 2016 远程桌面服务在哪

Azure VM 在未通过远程桌面连接时暂停正在运行的软件

C#远程桌面遗留控制台应用程序[关闭]