如何在断开会话的Windows Server中使用SendInput模拟鼠标移动?
问题描述
在带桌面体验的Windows Server中,通过C#调用SendInput()函数模拟鼠标移动,代码如下:
using Windows.Win32; using Windows.Win32.UI.Input.KeyboardAndMouse; using System.ComponentModel; using System.Threading; using System.Runtime.InteropServices; for (int i = 0; i < 5; i += 1) { var inputs = new INPUT[] { new() { type = INPUT_TYPE.INPUT_MOUSE, Anonymous = new INPUT._Anonymous_e__Union { mi = new MOUSEINPUT { dx = 0, dy = 0, mouseData = 0, dwFlags = MOUSE_EVENT_FLAGS.MOUSEEVENTF_ABSOLUTE | MOUSE_EVENT_FLAGS.MOUSEEVENTF_MOVE, time = 0, dwExtraInfo = 0, }, }, } }; if (PInvoke.SendInput(inputs, Marshal.SizeOf<INPUT>()) == 0) { throw new Win32Exception(Marshal.GetLastWin32Error()); } Thread.Sleep(2000); }
保持远程桌面会话开启时代码运行正常,但断开会话后SendInput()返回0x5(ERROR_ACCESS_DENIED);在虚拟机中关闭连接窗口后,同样执行失败。需要解决如何在不保持连接的情况下正常使用SendInput()。
解决方案
保持用户会话持续活跃
断开远程桌面或虚拟机连接后,系统会自动挂起或注销用户会话,而SendInput()依赖活跃的交互式桌面会话才能正常工作。可通过自动登录实现会话持续:- 运行
netplwiz打开用户账户设置窗口 - 取消勾选「要使用本机,用户必须输入用户名和密码」选项
- 点击确定后输入自动登录的账号和密码,重启服务器后会自动进入用户桌面,保持会话活跃
- 运行
配置远程桌面会话超时策略
通过组策略禁用会话自动注销:- 运行
gpedit.msc打开组策略编辑器 - 导航到「计算机配置 > 管理模板 > Windows组件 > 远程桌面服务 > 远程桌面会话主机 > 会话时间限制」
- 将「设置断开连接的会话的时间限制」和「设置活动但空闲的远程桌面服务会话的时间限制」均设置为「已禁用」
- 运行
以交互式服务方式运行程序
如果程序需以服务形式后台运行,需配置服务允许与桌面交互:- 在服务管理器中找到目标服务,右键选择「属性」
- 切换到「登录」选项卡,勾选「允许服务与桌面交互」
- 重启服务后,程序可在后台访问桌面会话,调用
SendInput()不受连接状态影响
使用会话保持工具
可借助第三方工具(如AutoHotkey脚本、SessionKeepAlive等)模拟轻微用户操作,防止系统挂起会话,但优先推荐系统自带配置方案,稳定性更高
内容的提问来源于stack exchange,提问作者Greg
相关产品推荐
相关产品推荐

