C#/.NET基于Topshelf创建Windows服务的守护程序作为服务启动的客户端桌面程序不显示UI界面的问题分析和解决方案

C#开发 作者: Rector 604 次阅读 · 读完约需 5 分钟 1 收藏 收藏本文

郑重申明:本文未经许可,禁止任何形式转载

前言

在上一篇文章《在C#/.NET应用程序开发中创建一个基于Topshelf的应用程序守护进程(服务)》的最后,我给大家抛出了一个遗留的问题—在将TopshelfDemoService程序作为Windows服务安装的情况下,由它守护并启动的客户端程序是没有UI界面的。到这里,我们得分析为什么会出现这个问题,为什么在桌面应用程序模式下可以显示UI界面,而在服务模式下没有UI界面?

分析问题(Session 0 隔离)

通过查阅资料,这是由于Session 0 隔离作用的结果。那么什么又是Session 0 隔离呢?

在Windows XP、Windows Server 2003 或早期Windows 系统时代,当第一个用户登录系统后服务和应用程序是在同一个Session 中运行的。这就是Session 0 如下图所示:

但是这种运行方式提高了系统安全风险,因为服务是通过提升了用户权限运行的,而应用程序往往是那些不具备管理员身份的普通用户运行的,其中的危险显而易见。

从Vista 开始Session 0 中只包含系统服务,其他应用程序则通过分离的Session 运行,将服务与应用程序隔离提高系统的安全性。如下图所示:

这样使得Session 0 与其他Session 之间无法进行交互,不能通过服务向桌面用户弹出信息窗口、UI 窗口等信息。这也就是为什么刚才我说那个图已经不能通过当前桌面进行截图了。

潜在的问题

解决方案

在了解了Session 0 隔离之后,给出一些有关创建服务程序以及由服务托管的驱动程序的建议:

1、与应用程序通信时,使用RPC、命名管道等C/S模式代替窗口消息
2、如果服务程序需要UI与用户交互的话,有两种方式:
①用WTSSendMessage来创建一个消息框与用户交互
②使用一个代理(agent)来完成跟用户的交互,服务程序通过CreateProcessAsUser创建代理。
并用RPC或者命名管道等方式跟代理通信,从而完成复杂的界面交互。
3、应该在用户的Session中查询显示属性,如果在Session 0中做这件事,将会得到不正确的结果。
4、明确地使用Local或者Global为命名对象命名,Local/为Session/<n>/BaseNamedObject/,Global/为BaseNamedObject/
5、将程序放在实际环境中测试是最好的方法,如果条件不允许,可以在XP的FUS下测试。在XP的FUS下能工作的服务程序将很可能可以在新版系统中工作,注意XP的FUS下的测试不能检测到在Session 0下跟视频驱动有关的问题

本文我们的服务程序将通过CreateProcessAsUser创建代理来实现Session 0隔离的穿透。

在项目[TopshelfDemoService]中创建一个静态扩展帮助类ProcessExtensions.cs,代码如下:

修改ProcessHelper.cs为如下代码:

其中更改了方法RunProcess()的调用方式。

重新编译服务程序项目[TopshelfDemoService],并将它作为Windows服务安装,最后启动服务。守护进程服务将启动一个带UI界面的客户端程序。大功告成!!!

我是Rector,希望本文的关于Topshelf服务和守护程序设计对需要的朋友有所帮助。

感谢花你宝贵的时间阅读!!!

参数资料

穿透Session 0 隔离(一)
Windows中Session 0隔离对服务程序和驱动程序的影响
CreateProcessAsUser

源代码下载

本文示例程序源代码托管地址(github): 示例源代码下载

阅读了该文章的人还浏览了...

本文永久链接码友网 » C#/.NET基于Topshelf创建Windows服务的守护程序作为服务启动的客户端桌面程序不显示UI界面的问题分析和解决方案

发布于: 2019-04-11 10:51:03
分享扩散:

发表评论

登录用户才能发表评论, 请 登 录 或者 注册