为每个进程、用户或会话获取非交互式用户的 Window Station?

Posted

技术标签:

【中文标题】为每个进程、用户或会话获取非交互式用户的 Window Station?【英文标题】:Get Window Station for a non-interactive user per process, user or session? 【发布时间】:2010-06-18 20:52:33 【问题描述】:

当使用 CreateProcessAsUser 时,我们传递 STARTUPINFO 和 lpDesktop NULL,目标是 winsta0/default,交互式用户的交互式桌面。

我希望在第二个非交互式用户(例如远程桌面用户)的另一个会话中定位窗口站。

我认为它不可能是 winsta0,因为它是为单个交互式用户保留的。

我在这里查看函数列表: http://msdn.microsoft.com/en-us/library/ms687107(v=VS.85).aspx

我可以枚举机器上的窗口站,但是如何识别哪个窗口站连接到哪个用户/进程/会话?

每个窗口站都连接到一个会话 每个进程都有一个目标窗口站

但是,例如,如果我有一个进程或会话 ID,我如何确定它与哪个 Window Station 相关联?

【问题讨论】:

【参考方案1】:

在 WinXP/Win2K3 或更高版本上,您可以执行以下操作:

    调用 WTSEnumerateSessions 以获取活动会话信息的列表(这也会为您提供与每个会话关联的窗口站名称)。 将会话 ID 传递给 WTSQueryUserToken。 将令牌传递给 GetTokenInformation 以获取用户的 SID。 将用户的 SID 传递给 LsaLookupSids 以获取用户和域名。

另外,如果您想识别哪个会话是活动控制台会话,您可以将会话 id 与 WTSGetActiveConsoleSessionId 的返回值进行比较。

但是,正如 Franci 所提到的,我建议使用从 WTSQueryUserToken 返回的令牌通过 CreateProcessAsUser 在目标桌面上启动一个进程。您必须通过 DuplicateTokenEx 将其从模拟令牌转换为主令牌,但它适用于 WinXP 或更高版本,Microsoft 将其记录为从 Vista 上的服务桌面启动交互式应用程序的“首选”方式和更高。

【讨论】:

【参考方案2】:

您可以使用GetUserObjectinformation 获取与该窗口站关联的用户的 SID。

至于从进程中找到Window Station: - 获取进程的***窗口句柄 - 枚举窗口站 (EnumWindowStations) - 枚举每个窗口站的桌面 (EnumDesktops) - 枚举每个桌面的窗口 (EnumDesktopWindows),直到找到匹配项。

是的,这不是一个简单的方法,但它应该可以解决您的问题。

注意:在 Vista 和 Win7 上,交互式用户不在 winsta0 中。 Winsta0 仅为系统和服务保留,交互式用户获得一个新的 Windows 站,并被视为(大部分)与 TS 用户相同的方式。

【讨论】:

这很好用,并给了我 Winstation 和 Desktop 的名称。我可以通过GetWindowThreadProcessId从EnumWindows的Hwnd中提取pid。我在获取 WindowStation 的句柄时遇到问题。 EnumWindowStations 的回调只返回一个名称,没有句柄 在 Win7 上,EnumWindowStations 从服务运行,在我切换用户(多用户切换)之后,似乎只枚举了显然不是交互式或非交互式用户的 Winsta0。根据msdn.microsoft.com/en-us/library/ms682644(VS.85).aspx 和msdn.microsoft.com/en-us/library/ms687391(v=VS.85).aspx 服务应该能够枚举盒子上的所有窗口站? 更进一步,从EnumWindowStations,我只能枚举WinSta0和各种服务和mswindowstations。没有用户窗口站。另外,根据 OpenWindowStation 的文档,它仅适用于当前会话。这似乎意味着它在技术上无法打开除第一站以外的任何东西。我似乎无法打开除 WinSta 0 之外的任何其他站点。msdn.microsoft.com/en-us/library/ms684339(v=VS.85).aspx。 “Winsta0 仅用于系统和服务,交互式用户获得一个新的 Windows 站” - 如果我理解正确,您是说登录用户不使用 WinSta0。这是不正确的。 WinSta0 是唯一的交互式窗口站,但它每个会话 存在。所以会话 0(这是运行服务的会话)有一个 WinSta0(以及其他),而会话 1(通常是本地登录的用户)有一个 WinSta0。无论会话如何,都只能在 WinSta0 中显示 GUI。 有兴趣的可以看看this article。

以上是关于为每个进程、用户或会话获取非交互式用户的 Window Station?的主要内容,如果未能解决你的问题,请参考以下文章

守护进程

从会话 id 获取正确的令牌

从服务启动用户会话中的进程

每个实例的 AppDomain 或进程?

会话技术cookie和session详解

用户和组管理及权限