具有快速用户切换和远程桌面功能的用户帐户

Windows XP 用户帐户允许多个用户同时登录,每个用户都有自己的设置并运行自己的应用程序。 由于不必让一个用户退出登录即可访问另一个用户,因此可以使用快速用户切换功能轻松访问每个用户的桌面。 用户帐户还包括个人终端服务器功能或远程桌面,因此用户能够从远程系统访问其桌面帐户。

论述了以下主题。

基础结构使用要求

从 Windows 2000 继承的底层基础结构支持用户数据、用户设置和计算机设置的状态分离。 利用此基础结构时,若要在 Windows XP 下成功运行应用程序,需要满足以下条件。

  • 默认使用“我的文档”文件夹来存储用户创建的数据。
  • 对应用程序数据进行正确分类和存储。
  • 出现“拒绝访问”消息时进行正常的降级。

临时文件、内存映射文件和文档都应存储在用户配置文件目录的相应子目录中。 使用 SHGetFolderLocationSHGetFolderPath 确定这些文件的适当存储位置。 将 CSIDL_APPDATA 标志传递给这些函数会返回文件系统目录的路径,该目录充当特定于应用程序的数据的公共存储库。 对于那些应该会在用户更改时更改的数据(例如临时文件),请使用标志 CSIDL_LOCAL_APPDATA 代替 CSIDL_APPDATA

上面列出的要求是 Microsoft Certification 计划中的要求的一部分。 有关详细信息,请参阅 Windows 桌面应用的认证要求页面。

与现有应用程序的兼容性

快速用户切换和个人终端服务器都使用终端服务技术,因此与大多数早期的 Microsoft Win32 应用程序兼容。 如果应用程序符合 Windows 2000 徽标要求,实现基本的配置文件分离和电源管理功能,则该应用程序应该会在单独的 Windows XP 用户帐户下正常运行。

注册会话切换通知

通常情况下,发生桌面切换时不需要通知应用程序。 但是,如果在运行应用程序(例如访问串行端口或其他共享资源的应用程序)时所使用的帐户是当前桌面的情况下必须通知应用程序,则应用程序可以注册桌面切换通知。 若要注册通知,请使用 WTSRegisterSessionNotification 函数。

调用该函数后,具有句柄 hWnd 的窗口就会进行注册,以通过其 WndProc 函数接收 WM_WTSSESSION_CHANGE 消息。 会话 ID 在 lParam 参数中发送,指示生成了消息的事件的代码在 wParam 中作为以下标志之一发送。

  • WTS_CONSOLE_CONNECT
  • WTS_CONSOLE_DISCONNECT
  • WTS_REMOTE_CONNECT
  • WTS_REMOTE_DISCONNECT
  • WTS_SESSION_LOGOFF
  • WTS_SESSION_LOGON

应用程序可以使用此消息来跟踪其状态以及释放和获取特定于控制台的资源。 用户桌面可以在远程控制和控制台控制之间动态切换。 应用程序应使用 WM_WTSSESSION_CHANGE 消息来与远程或本地连接状态同步。

当进程不再需要这些通知或即将终止时,它应调用 WTSUnRegisterSessionNotification 来取消注册其通知。

重要

传递给 WTSRegisterSessionNotification 的 hWnd 值采用引用计数,因此你必须对 WTSUnRegisterSessionNotification 进行相等数量的调用,以确保释放所有分配的资源。

 

确保仅运行应用程序的一个实例

许多应用程序必须确保它们只运行一个实例。 在 Windows XP 中,有多种方法可以实现此目的。 其中包括:

  • 使用 FindWindowFindWindowEx 搜索应用程序打开的已知窗口。 如果该窗口已打开,可以将其用作应用程序已在运行的指示。
  • 在应用程序打开时创建互斥或信号灯对象,在应用程序终止时关闭该对象。 每个桌面的全局对象命名空间是独立的,因此每个桌面都有独一无二的互斥和信号灯对象列表。

在所有会话中关闭应用程序

应用程序可能需要在所有会话中自行关闭。 例如,同时在两个或多个会话中运行的应用程序可能会从 Web 下载新文件。 然后,它可能需要自行关闭,并使用更新的位重启。 当然,需要在所有正在运行的会话中完成该操作。 应用程序应该编写为在收到通知时干净利落地退出。

与系统服务的交互

从程序的角度来看,需要解决以下情况。

  • 服务器进程接收来自客户端进程的直接请求。

    在这种情况下,消息可能是使用本地过程调用 (LPC) 或远程过程调用 (RPC) 来传输的。 使用 LPC 或 RPC 的 API 可以检索客户端令牌。 获取客户端令牌后,服务器可以在调用 CreateProcessAsUser 时使用它。 这会在正确的窗口站上启动该进程,假设客户端用户令牌具有会话标记(应该如此)。

    注意

    CreateProcessAsUser 目前不支持跨会话的句柄继承。

     

  • 服务器进程收到通知并需要显示 UI,但显示不需要是在当前用户的上下文中。

    在这种情况下,服务器进程可以复制其主进程令牌并更改相关会话标识符,使之匹配当前会话标识符。 可以使用 WTSGetActiveConsoleSessionId 函数获取当前会话标识符。

    注意

    若要设置令牌会话 ID,你需要 SE_TCB_PRIVILEGE。 只能将其作为在 NT AUTHORITY\SYSTEM 中运行的服务。

     

远程桌面和带宽

随着 Windows XP 中添加了远程桌面功能,应用程序应尽量不要使用超出需要的带宽,避免在以远程方式连接桌面时出现大量屏幕绘图和动画效果。 若要确定当前会话是否为远程会话,可以使用 SM_REMOTESESSION 调用 GetSystemMetrics。 但请注意,此调用不区分远程会话和断开连接的会话。