适用于 Citrix 的 SendKeys 替代方案
我最近为客户开发了一个虚拟键盘应用程序。该程序几乎适用于所有程序,但某些命令(如 {ENTER}
或 {DEL}
)不适用于 Citrix。是否有 SendKeys
的解决方法或替代方案?
编辑1:我尝试了SendInput方法(Windows输入模拟器使用SendInput),DEL键以及箭头键仍然不起作用。但是 ENTER 键可以使用。
编辑2:解决了。使用两个不同版本的 Citrix 进行测试。 这个问题对我帮助很大。:
Citrix 瘦客户端使用扫描码 keybd_event 的参数,即使 MS 说 它未使用,应该为 0。您需要 还提供物理扫描码 以便 Citrix 客户端获取它。 Citrix客户端也有重大问题 与生成的键盘输入 发送输入API。
我修补了 Windows 输入模拟器 中的代码:
// Function used to get the scan code
[DllImport("user32.dll")]
static extern uint MapVirtualKey(uint uCode, uint uMapType);
/// <summary>
/// Calls the Win32 SendInput method ...
/// </summary>
/// <param name="keyCode">The VirtualKeyCode to press</param>
public static void SimulateKeyPress(VirtualKeyCode keyCode)
{
var down = new INPUT();
down.Type = (UInt32)InputType.KEYBOARD;
down.Data.Keyboard = new KEYBDINPUT();
down.Data.Keyboard.Vk = (UInt16)keyCode;
// Scan Code here, was 0
down.Data.Keyboard.Scan = (ushort) MapVirtualKey((UInt16)keyCode, 0);
down.Data.Keyboard.Flags = 0;
down.Data.Keyboard.Time = 0;
down.Data.Keyboard.ExtraInfo = IntPtr.Zero;
var up = new INPUT();
up.Type = (UInt32)InputType.KEYBOARD;
up.Data.Keyboard = new KEYBDINPUT();
up.Data.Keyboard.Vk = (UInt16)keyCode;
// Scan Code here, was 0
up.Data.Keyboard.Scan = (ushort)MapVirtualKey((UInt16)keyCode, 0);
up.Data.Keyboard.Flags = (UInt32)KeyboardFlag.KEYUP;
up.Data.Keyboard.Time = 0;
up.Data.Keyboard.ExtraInfo = IntPtr.Zero;
INPUT[] inputList = new INPUT[2];
inputList[0] = down;
inputList[1] = up;
var numberOfSuccessfulSimulatedInputs = SendInput(2,
inputList, Marshal.SizeOf(typeof(INPUT)));
if (numberOfSuccessfulSimulatedInputs == 0)
throw new Exception(
string.Format("The key press simulation for {0} was not successful.",
keyCode));
}
I recently developed a virtual keyboard application for a customer. The program is working fine with almost all programs, but certain commands like {ENTER}
or {DEL}
are not working with Citrix. Is there are workaround or an alternative to SendKeys
?
Edit 1: I tried the SendInput method (Windows Input Simulator uses SendInput) and the DEL key as well as the arrow keys are still not working. The ENTER key works however.
Edit 2: Solved it. Tested with two different versions of Citrix. This question helped me a lot.:
Citrix thin clients uses the scancode
param of keybd_event even when MS says
it is unused and should be 0. You need
to supply the physical scancode aswell
for the citrix client to get it.
Citrix client also has major problem
with keyboard input generated with the
SendInput API.
I patched the code in Windows Input Simulator:
// Function used to get the scan code
[DllImport("user32.dll")]
static extern uint MapVirtualKey(uint uCode, uint uMapType);
/// <summary>
/// Calls the Win32 SendInput method ...
/// </summary>
/// <param name="keyCode">The VirtualKeyCode to press</param>
public static void SimulateKeyPress(VirtualKeyCode keyCode)
{
var down = new INPUT();
down.Type = (UInt32)InputType.KEYBOARD;
down.Data.Keyboard = new KEYBDINPUT();
down.Data.Keyboard.Vk = (UInt16)keyCode;
// Scan Code here, was 0
down.Data.Keyboard.Scan = (ushort) MapVirtualKey((UInt16)keyCode, 0);
down.Data.Keyboard.Flags = 0;
down.Data.Keyboard.Time = 0;
down.Data.Keyboard.ExtraInfo = IntPtr.Zero;
var up = new INPUT();
up.Type = (UInt32)InputType.KEYBOARD;
up.Data.Keyboard = new KEYBDINPUT();
up.Data.Keyboard.Vk = (UInt16)keyCode;
// Scan Code here, was 0
up.Data.Keyboard.Scan = (ushort)MapVirtualKey((UInt16)keyCode, 0);
up.Data.Keyboard.Flags = (UInt32)KeyboardFlag.KEYUP;
up.Data.Keyboard.Time = 0;
up.Data.Keyboard.ExtraInfo = IntPtr.Zero;
INPUT[] inputList = new INPUT[2];
inputList[0] = down;
inputList[1] = up;
var numberOfSuccessfulSimulatedInputs = SendInput(2,
inputList, Marshal.SizeOf(typeof(INPUT)));
if (numberOfSuccessfulSimulatedInputs == 0)
throw new Exception(
string.Format("The key press simulation for {0} was not successful.",
keyCode));
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
尝试使用 Windows 输入模拟器。 不确定它是否支持 Citrix,但它比 SendKeys 更强大。
Try using Windows Input Simulator. Not sure if it supports Citrix but it is much more powerfull compared to SendKeys.
尝试通过 P-Invoke 签名利用 API 调用(内容已编辑:这是现在的工作示例 - 我通过单击按钮将字符“a”发送到文本框):
Try to utilize API call wia P-Invoke signature (Content edited: this is now working example - I'm sending character 'a' to the textBox, on the click of a button) :
我还尝试使用 Windows InputSimulator 库控制 Citrix 应用程序。上面的代码看起来很有希望,因此我将其更新为与最新版本的 InputSimulator 一起使用(其中您使用 sim.Keyboard.Keypress 而不是 InputSimulator.SimulateKeyPress)。这是我添加到 InputSimulator 的代码,我很高兴地报告它按预期工作,并解决了我以前认为不可能的问题。非常感谢。
在 IKeyboardSimulator.cs 中:
在 KeyboardSimulator.cs 中:
I'm also attempting to control a citrix application using the windows InputSimulator library. Your code above looked promising, so I updated it to work with the latest version of InputSimulator (where you use sim.Keyboard.Keypress rather than InputSimulator.SimulateKeyPress). Here is the code that I added to InputSimulator, and I am delighted to report that it works as expected, and solves a problem that I previously thought was not possible. Thanks so much.
In IKeyboardSimulator.cs:
In KeyboardSimulator.cs:
对于Windows输入模拟器解决方案,您可以直接修改源代码,以便内置函数将使用虚拟键发送扫描码。
InputBuilder.cs:
通过这些更改,
TextEntry
、KeyPress
和ModifiedKeyStroke
将发送与传入的虚拟键关联的扫描代码。For the windows input simulator solution, you can modify the source code directly so that the built in functions will send scan codes with the virtual keys.
InputBuilder.cs:
With these changes
TextEntry
,KeyPress
, andModifiedKeyStroke
will send the scan codes associated with the virtual keys passed in.