2012-10-26 55 views
1

假设我在某个时间点从本地服务应用程序调用WTSEnumerateSessions并获取当前用户会话ID的列表。所以如果稍后我需要知道某个特定的用户会话是否仍然处于相同的状态,我可以依靠WTS_SESSION_INFO::SessionId是唯一的吗?如果没有,如何做到这一点?WTSEnumerateSessions API获得的会话ID是否唯一?

+1

你会考虑改变状态吗?如果用户登录并且现在被锁定,您是否会说会话处于相同状态? – ixe013

回答

2

Windows为每个登录会话提供一个SID。 MSDN has sample code to look it up,并且对于给定的登录会话保证唯一且恒定。如果用户注销并重新登录,他将被归入新的登录SID。

如果同一用户在本地登录并在同一位置进行远程登录,则每个登录会话都会有一个不同的登录SID。下图显示了我的意思:

Alice has two logon session, with distinct Logon SID

(免责声明 - 我偷了它从一个blog post of mine

你可以用这个命令得到登录SID。在不编写任何代码的情况下播放假设情景可能是有用的。

c:\>whoami /logonid 
S-1-5-5-0-329693570 

在Windows Server 2008上测试。在其他版本上的YMMV。

+0

很好的解释,图表(虽然是自剽窃)和C++代码。虽然我有一个关于代码示例的问题。它使用令牌句柄来查找登录SID,但我没有令牌。或者,我应该说,我如何得到它? – c00000fd

+1

@ user843732您可以使用[WTSQueyUserToken](http://msdn.microsoft.com/en-us/library/windows/desktop/aa383840%28v=vs.85%29.aspx)获取令牌。致电***的应用程序必须在本地系统帐户的上下文中运行,并具有“SE_TCB_NAME”权限才能使该呼叫生效。 –

+0

好点。谢谢。 – c00000fd

0

会话ID与安全ID不同。会话可能会有人在某个状态下登录,或者可能没有人登录。您可以调用WTSEnumerateSessions并发现有人在会话1登录,稍后该人员可以注销,稍后其他人可以登录并且Windows可能会给他们会话1,然后再次调用WTSEnumerateSessions。因此,在经历两次更改并由不同用户使用之前,状态可能与之前相同。你称这是独一无二的吗?我不知道你独特的意思。

+0

那么有什么方法可以在当时对所有登录的用户帐户进行更具体的(即唯一的)引用? – c00000fd

2

会话ID被分配为登录时最低的未使用号码。

因此,如果我有ID 1,然后注销,并且您登录,您将获得ID 1,因为1在登录时可用。

如果我从未注销过,由于ID 1正在使用中,您将获得ID 2。如果我然后注销,并且您留在下一个用户将再次分配ID 1(不是3),因为1是最低的未使用的数字。

+0

那么这个API返回的会话ID是什么?该ID一旦返回就会失效,因为在此期间,用户可能已注销,并且新用户可能已登录,并且新用户将具有相同的会话ID ... – c00000fd

+0

假设您要查询ID,然后立即做出您需要的任何内容,例如向所有登录用户发送消息,您将调用WTSEnumerateSessions并为每个结果立即调用[ WTSSendMessage](http://msdn.microsoft.com/en-us/library/windows/desktop/aa383842%28v=vs.85%29.aspx)。这两种操作都需要一秒钟的时间才能完成,而且很可能一个人不会登录,而另一个人将在这两个呼叫之间的秒数部分登录。 –

+0

另一个常见和有用的例子是如果我想要一个实用程序来记录某人。我会调用一次WTSEnumerateSessions来填充我的UI,当用户选择注销时,我再次调用WTSEnumerateSessions,我检查用户名和SessionID是否仍然与我在UI中显示的相同(以防万一用户已经在间隔时间内注销)然后我调用[WTSLogoffSession](http://msdn.microsoft.com/en-us/library/windows/desktop/aa383836%28v=vs.85%29.aspx)通过传入刚刚检查过的会话ID来注销用户,我知道这是有效的。 –