如何在锁定的VDI上模拟键鼠?VB.NET KVM实现方案咨询
解决方案:VB.NET实现VDI锁定时的KVM输入模拟
一、Citrix锁定后输入失效的原因
Citrix Client在VDI锁定状态下会接管本地输入设备的控制权,常规的SendKeys或Windows Forms输入模拟会被拦截,必须使用系统级底层API或KVM硬件厂商SDK才能绕过限制。
二、系统级输入模拟(软件KVM方案)
使用Windows user32.dll中的SendInput函数实现底层输入模拟,该方法属于系统级操作,不易被Citrix拦截。
VB.NET代码实现
首先导入Windows API并封装输入模拟工具类:
Imports System.Runtime.InteropServices Public Class InputSimulator ' 定义输入结构体 <StructLayout(LayoutKind.Sequential)> Private Structure INPUT Public type As Integer Public mi As MOUSEINPUT Public ki As KEYBDINPUT Public hi As HARDWAREINPUT End Structure <StructLayout(LayoutKind.Sequential)> Private Structure MOUSEINPUT Public dx As Integer Public dy As Integer Public mouseData As Integer Public dwFlags As Integer Public time As Integer Public dwExtraInfo As IntPtr End Structure <StructLayout(LayoutKind.Sequential)> Private Structure KEYBDINPUT Public wVk As Short Public wScan As Short Public dwFlags As Integer Public time As Integer Public dwExtraInfo As IntPtr End Structure <StructLayout(LayoutKind.Sequential)> Private Structure HARDWAREINPUT Public uMsg As Integer Public wParamL As Short Public wParamH As Short End Structure ' API常量定义 Private Const INPUT_KEYBOARD As Integer = 1 Private Const KEYEVENTF_KEYUP As Integer = &H2 Private Const VK_LWIN As Short = &H5B Private Const VK_L As Short = &H4C ' 导入SendInput API <DllImport("user32.dll", SetLastError:=True)> Private Shared Function SendInput(nInputs As Integer, ByRef pInputs As INPUT, cbSize As Integer) As Integer End Function ' 模拟单键按下并释放 Public Shared Sub SimulateKeyPress(keyCode As Short) Dim inputDown As INPUT = New INPUT() inputDown.type = INPUT_KEYBOARD inputDown.ki.wVk = keyCode inputDown.ki.dwFlags = 0 Dim inputUp As INPUT = New INPUT() inputUp.type = INPUT_KEYBOARD inputUp.ki.wVk = keyCode inputUp.ki.dwFlags = KEYEVENTF_KEYUP Dim inputs() As INPUT = {inputDown, inputUp} SendInput(inputs.Length, inputs(0), Marshal.SizeOf(GetType(INPUT))) End Sub ' 模拟Win+L组合键(示例解锁操作) Public Shared Sub SimulateWinL() Dim winDown As INPUT = New INPUT() winDown.type = INPUT_KEYBOARD winDown.ki.wVk = VK_LWIN winDown.ki.dwFlags = 0 Dim lDown As INPUT = New INPUT() lDown.type = INPUT_KEYBOARD lDown.ki.wVk = VK_L lDown.ki.dwFlags = 0 Dim lUp As INPUT = New INPUT() lUp.type = INPUT_KEYBOARD lUp.ki.wVk = VK_L lUp.ki.dwFlags = KEYEVENTF_KEYUP Dim winUp As INPUT = New INPUT() winUp.type = INPUT_KEYBOARD winUp.ki.wVk = VK_LWIN winUp.ki.dwFlags = KEYEVENTF_KEYUP Dim inputs() As INPUT = {winDown, lDown, lUp, winUp} SendInput(inputs.Length, inputs(0), Marshal.SizeOf(GetType(INPUT))) End Sub End Class
结合你已有的SystemEvents.SessionSwitch监控逻辑:
Imports Microsoft.Win32 Public Class VdiLockMonitor Private Sub SessionSwitchHandler(sender As Object, e As SessionSwitchEventArgs) If e.Reason = SessionSwitchReason.SessionLock Then ' VDI锁定时执行KVM输入模拟 InputSimulator.SimulateWinL() ' 替换为你需要的输入操作 End If End Sub ' 启动监控 Public Sub StartMonitoring() AddHandler SystemEvents.SessionSwitch, AddressOf SessionSwitchHandler End Sub ' 停止监控 Public Sub StopMonitoring() RemoveHandler SystemEvents.SessionSwitch, AddressOf SessionSwitchHandler End Sub End Class
三、物理KVM硬件控制方案
如果使用实体KVM设备,需依赖厂商提供的SDK(如Avocent、HP等品牌均有.NET兼容SDK):
- 下载对应KVM设备的SDK,引入项目中的DLL或COM组件
- 在
SessionSwitch锁定事件触发时,调用SDK提供的方法(如切换端口、发送解锁指令等)
四、关键注意事项
- 权限要求:程序需以管理员权限运行,否则
SendInput可能无法生效 - Citrix兼容性:部分Citrix版本可能拦截虚拟键码输入,可改用扫描码模式(修改
KEYBDINPUT的wScan字段) - 硬件依赖:物理KVM的控制逻辑完全遵循厂商文档,需自行适配设备型号
内容的提问来源于stack exchange,提问作者Mr.Ious
相关产品推荐
相关产品推荐

