微软官网的翻译整理
原文:https://docs.microsoft.com/zh-cn/windows/win32/winstation/window-stations-and-desktops
最后有几点是自己总结的,用红色标出
窗口站:
- 一个窗口站包含一个剪切板、一个原子表、和一个或多个桌面对象
- 窗口站创建时和进程相关联,并且被放到当前的会话
- 只有WinSta0可以有交互界面,和接收用户输入,其他窗口站是不可以有用户交互的
- 远程登录的用户会新建一个会话,每个会话和自己的窗口站关联(窗口站名为WinSta0)
- 系统会创建默认的窗口站和桌面,并且和当前的用户关联WinSta0\Default
- CreateWindowStation 创建窗口站
- 如果服务进程所在的会话没有窗口站系统会创建一个窗口站(如果是LocalSystem账户,并且没有SERVICE_INTERACTIVE_PROCESS属性,则名称为Service-0x0-3e7$,不能交互。如果是用户账户那么名称为Service-0xZ1-Z2$,Z1是SID的高部分,Z2是SID的低部分。上面两种情况都是不可交互的)和桌面(Default)
- 程序调用User32或者GDI函数时自动连接,如果调用了SetProcessWindowStation或者从父进程继承了指定的窗口站,那么就会连接到指定的窗口站。或者连接创建进程指定的STARTINFO里面的lpDesktop。如果都没有的话,则会连接到交互进程的窗口站。如果从父进程继承了多个,那么连接行为是不确定的。
- 连接过程中不能调用CloseWindowStation来关闭
- 调用GetSecurityInfo和SetSecurityInfo来设置安全描述符
桌面:
- 有逻辑显示界面,并且包含用户界面对象(比如窗口,菜单,钩子等),时安全的对象
- 和窗口站关联,被放到创建的线程
- 窗口消息只能在同一个桌面中传递,钩子过程也只能接收进程所在桌面的消息
- 一个窗口站只有一个活动的桌面(用来显示用户界面和接收用户输入)可以使用OpenInputDesktop获取输入桌面的句柄,有权限的应用程序可以使用SwitchDesktop来切换不同的输入桌面
- 交互窗口站中有三个桌面:Default(用户已登录), ScreenSaver, Winlogon(用户登录界面,或者 CTRL+ALT+DEL 或者UAC 对话框弹出)。WinLogon桌面有非常严格的账户限制,应用程序通常没有账户的SID,所以不能从WinLogon桌面切换到其他界面
- CreateDesktop和CreateDesktopEx 可创建的桌面数量由系统桌面堆限制
- 当连接窗口站后,系统会赋值桌面到线程标记连接。如果调用了SetThreadDesktop则连接到指定的桌面,否则会连接到从父进程继承来的,如果都没有的话,则会连接创建进程时STARTINFO里面的lpDesktop,否则是连接Default桌面。如果从父进程继承了多个,那么连接行为是不确定的。
- 连接过程中不能调用CloseDesktop来关闭。
- 所有的句柄被关闭,桌面就会被销毁
- 当调用SwitchDesktop 切换桌面之后,如果想在新的桌面创建窗口,需要在新的线程中
sysinternals 里面的desktops.exe 在切换桌面之后新建了一个explorer.exe,并且设置了WH_KEYBOARD_LL钩子来响应win+E系列的快捷键
附上本人写的一个窗口切换的小工具及源码:
https://github.com/lsjgithub/MultiDesktop
https://github.com/lsjgithub/MultiDesktop.git
相关函数:
相关注册表路径:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders