110,537
社区成员
发帖
与我相关
我的任务
分享
+ Session 0 (会话0,所有服务运行在此会话,服务启动的程序,也运行在此会话)
|---+ WinSta0
| |---- WinLogon
| |---- Default
| + Service-0x0-3e4$
| + Service-0x0-3e5$
| + Service-0x0-3e7$
| + mswindowstation
|
+ Session 3 (用户A登录后,用户A的程序,运行在此会话)
|----+ WinSta0
| |---- WinLogon
| |---- ScreenSaver
| |---- Default (用户A的默认桌面,显示桌面背景,状态栏,托盘栏等等)
| |---- Desktop 2
| |---- Desktop 3
|
+ Session 4 (用户B登录后,用户B的程序,运行在此会话)
|----+ WinSta0
| |---- WinLogon
......
其中,
* Session就是用户会话,每个登录用户将会由一个用户对话。上图描述了用户A和用户B同时登录的情形(快速用户切换)。
* WinSta0就是一个允许用户交互的WindowStation【注二】。
* 每个WinSta0可以有多个桌面。有个默认的桌面就是平时我们登录后看到的带背景和状态栏/托盘栏的桌面【注三】。
在VisualStudio下调试WinForm程序,将运行在该桌面。
* Windows其实支持多个桌面,Windows10下可以直接用Ctrl+Win+D来创建一个桌面(Ctrl+Win+F4删除)。
为了演示,我创建了另两个桌面,这就是那些Default ,Desktop 2,Desktop 3的来由。
讲了一些概念,为什么Windows服务程序中调用exe不能被直接观察到,就很容易理解了:
- 服务程序运行在session 0,
- 服务程序运行的子进程,将默认继承父进程的上下文,并运行在session 0,它不能显示到登录用户的WinSta0下。
- 你作为登录用户,将运行在比如Session 1并使用默认WinSta0/Default桌面,
你的C#窗口程序或者控制台程序,也运行在Session1,WinSta0/Default桌面
- 因此,“用C#的窗口程序或者控制台程序调用这个a.dll文件,a.dll中再调用b.exe,这3种方法都可以成功”
- 但是,“c#的windows服务程序中调用a.dll(c++编写),在dll中调用了一个b.exe外部文件没有反应”
解决方法:
b.exe可以运行服务逻辑(比如做图像分析,数据运算等),但是,b.exe不要显示界面,不要进行用户交互。
监控b.exe,要从进程管理上监视,而不是依赖于是否看的见窗口。
那些STARTF_USESHOWWINDOW,wShowWindow 就不要写了;ShellExecuteA就不要用了,因为服务会话下不见的有Shell。
【注一】
https://techcommunity.microsoft.com/t5/Ask-The-Performance-Team/Application-Compatibility-Session-0-Isolation/ba-p/372361
【注二】
https://docs.microsoft.com/en-us/windows/win32/termserv/terminal-services-sessions
【注三】
https://docs.microsoft.com/en-us/windows/win32/winstation/desktops