Instsrv+Srvany配置自启动服务时DXGI捕获登录屏异常问题
问题根源与解决方案
这个问题的核心其实是Windows的会话隔离机制在搞鬼,咱们一步步拆解清楚:
为什么用Srvany注册成服务会失败?
从Windows Vista开始,微软引入了Session 0隔离机制:系统服务默认会在Session 0(非交互式的后台会话)运行,而登录屏幕、用户桌面这类交互式界面,都在Session 1及以后的独立会话里。
你用Instsrv+Srvany把dxgiSample.exe包装成服务后,它会默认在Session 0执行:
- DXGI的
EnumOutputs返回DXGI_ERROR_NOT_CURRENTLY_AVAILABLE(0x887A0022),是因为Session 0根本没有绑定任何物理显示输出,自然枚举不到可用的显示设备; OpenInputDesktop返回错误1(ERROR_INVALID_FUNCTION),也是因为Session 0不存在可供交互的桌面环境,调用这个API自然无效。
为什么PsExec64能正常运行?
你用的参数PsExec64.exe -s -d -i dxgiSample.exe里,有两个关键作用:
-s让程序以系统权限运行,满足捕获登录屏幕所需的高权限要求;-i是核心原因:这个参数指定程序在当前的交互式会话(也就是登录屏幕所在的Session)启动,这样程序就能访问到该会话绑定的显示输出和桌面对象,DXGI枚举、桌面操作自然都能正常工作。
解决办法:用任务计划替代Srvany实现自动启动
Srvany本质是把程序塞进Session 0的服务容器,没法直接让它跑到登录屏幕所在的交互式会话里,最可靠的替代方案是用任务计划程序,步骤如下:
- 打开「任务计划程序」,点击「创建任务」:
- 「常规」选项卡:勾选「使用最高权限运行」,选择「不管用户是否登录都要运行」(确保登录屏幕阶段也能触发);
- 「触发器」选项卡:添加触发器,选择「在工作站解锁时」(对应登录屏幕解锁场景)或者「在用户登录时」(根据你的捕获需求选择);
- 「操作」选项卡:添加操作,选择「启动程序」,指定
dxgiSample.exe的完整路径; - 「设置」选项卡:可选勾选「如果任务失败,每隔X分钟重试」,取消勾选「如果任务运行时间超过X小时就停止」。
- 保存任务后,重启系统测试,登录屏幕阶段程序应该能正常捕获,不会再出现之前的DXGI和桌面操作错误。
如果非要坚持用服务方式,也可以通过修改注册表或组策略让服务在交互式会话运行,但Windows 7及以后对这种方式做了严格限制,兼容性很差,不推荐。
内容的提问来源于stack exchange,提问作者hello




