Windows 10 向用户展示的新功能之一是对额外“虚拟桌面”的支持。现在,用户可以创建额外的界面来使用窗口。这个想法其实并不新颖——在Linux世界中已经存在多年(例如KDE、Gnome等桌面环境),用户可以使用4个虚拟桌面。这个想法的初衷是为了避免杂乱无章,例如,一个桌面可以用来浏览网页,另一个桌面可以用来进行所有的开发工作,而第三个桌面则可以用来运行所有的社交/工作应用(如Outlook、WhatsApp、Facebook等,无论什么应用)。 要在Windows 10上创建一个额外的虚拟桌面,请点击任务栏上的“任务视图”按钮,然后点击标有加号(+)的“新建桌面”按钮。
现在,您可以通过点击相应的桌面按钮来在虚拟桌面之间切换,然后像往常一样启动应用程序。甚至(通过再次点击任务视图)可以将窗口从一个桌面移动到另一个桌面,或者要求某个窗口在所有桌面上都可见。 多年来,Sysinternals工具集中一直有一个名为“Desktops”的工具。它同样允许创建最多4个桌面,用户可以在这些桌面上启动应用程序。问题是——这个Desktops工具与Windows10的虚拟桌面功能是一样的吗?不完全一样。 首先,让我们了解一些背景信息。在会话对象下的内核对象层次结构中,存在窗口站、桌面和其他对象。下面是一个总结这种树状关系的图示:
从图示中可以看出,一个会话包含一组窗口站。其中一个窗口站可以是交互式的,意味着它可以接收用户输入,并且它总是被命名为winsta0。如果存在其他窗口站,则它们是非交互式的。 每个窗口站包含一组桌面。这些桌面中的每一个都可以容纳窗口。因此,在任何给定时刻,交互式用户都可以与winsta0下的一个桌面进行交互。登录时,会创建一个名为“默认”的桌面,所有正常的窗口都会出现在这个桌面上。例如,如果您按Ctrl+Alt+Del,您将被转移到由winlogon进程创建的另一个名为“Winlogon”的桌面。这就是为什么您的正常窗口会“消失”——您已经切换到了另一个可能存在不同窗口的桌面。这种切换是通过一个已经文档化的函数——SwitchDesktop来实现的。 这里就是Windows 10虚拟桌面和Sysinternals桌面工具之间的区别所在。Sysinternals桌面工具实际上是通过使用CreateDesktop API来创建桌面对象的。在那个桌面上,它启动了Explorer.exe,以便在那个桌面上创建一个任务栏——最初桌面上什么都没有。桌面如何启动一个默认在另一个桌面上创建窗口的进程呢?这可以通过在STARTUPINFO结构的lpDesktop成员中指定桌面名称,使用正常的CreateProcess函数来实现。其格式为“windowstation\desktop”。因此,在桌面工具的情况下,它类似于“winsta0\Sysinternals Desktop 1”。那么,我如何知道Sysinternals桌面对象的名称呢?可以使用EnumDesktops API来枚举桌面。我编写了一个小工具,用于枚举当前会话中的窗口站和桌面。当使用“desktops”创建了一个额外的桌面时,以下是一个示例输出:
在Windows 10的虚拟桌面功能中,实际上并没有创建新的桌面。Win32k.sys只是操纵窗口的可见性,仅此而已。您能猜到这是为什么吗?为什么Windows10不为其虚拟桌面功能使用CreateDesktop/SwitchDesktop API呢? 原因与桌面对象存在的一些限制有关。首先,一个绑定到桌面的窗口(从技术上讲是一个线程)不能被切换到另一个桌面;换句话说,无法将一个窗口从一个桌面转移到另一个桌面。这是有意为之,因为桌面提供了一些保护。例如,使用SetWindowsHookEx设置的钩子只能设置在当前桌面上,因此不能影响其他桌面上的其他窗口。再以Winlogon桌面为例,它有一个严格的安全描述符,防止非系统级用户访问该桌面。否则,该桌面可能会被篡改。 Windows 10中的虚拟桌面并不是为了安全目的而设计的,而是为了灵活性和便利性(安全总是与便利性“相矛盾”)。因此,可以在桌面之间移动窗口,因为实际上根本没有发生“移动”。从内核的角度来看,所有内容仍然在同一个“默认”桌面上。
原文链接 |