我有一个由服务运行的应用程序。应用程序的配置方式只能在单个Windows用户帐户(即安装软件的用户)下运行。处理方式是在安装过程中,应用程序会保存启动安装的用户的用户名/域组合,然后保存服务,具体取决于用户会话是否处于活动状态,决定运行应用程序。
我们的一位客户报告该应用程序未在其帐户上运行,经过进一步调查后,我们发现在查询会话信息时出于某种原因,对于相同的会话ID,返回的域名不同。
这是WTSQuerySessionInformation的pInvoke:
[DllImport("Wtsapi32.dll", SetLastError = true)]
static extern bool WTSQuerySessionInformation(
IntPtr hServer,
uint sessionId,
WTS_INFO_CLASS wtsInfoClass,
out IntPtr ppBuffer,
out uint pBytesReturned
);
如果用户有活动会话,这就是我们获取服务检查的方式:
WTSEnumerateSessions(IntPtr.Zero, 0, 1, ref pSessionInfo, ref dwCount);
Int32 dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO));
Int32 current = (int)pSessionInfo;
uint bytes = 0;
for (int i = 0; i < dwCount; i++)
{
WTS_SESSION_INFO si = (WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)current, typeof(WTS_SESSION_INFO));
if (WTS_CONNECTSTATE_CLASS.WTSActive == si.State)
{
IntPtr userPtr = IntPtr.Zero;
IntPtr domainPtr = IntPtr.Zero;
//Check if the active session matches the saved username/domain
WTSQuerySessionInformation(IntPtr.Zero, (uint)si.SessionID, WTS_INFO_CLASS.WTSUserName, out userPtr, out bytes);
WTSQuerySessionInformation(IntPtr.Zero, (uint)si.SessionID, WTS_INFO_CLASS.WTSDomainName, out domainPtr, out bytes);
string sessionUName = Marshal.PtrToStringAnsi(userPtr);
string sessionDomain = Marshal.PtrToStringAnsi(domainPtr);
}
}
问题是当服务检测到用户的会话并尝试获取域名时,返回的名称与用户的实际域名不同,即使会话ID对于该特定用户是正确的。
如果它有助于从WTSQuerySessionInformation
返回的域名NTLAN_1
与完全不同于用户的实际域名。
我想知道WTSQuerySessionInformation
的pInvoke或上述代码中的任何调用是否有任何问题。还想知道NTLAN_1
域是否与某种服务或任何类型的RDP应用程序相关联。
编辑:
经过多次谈判后,我设法得到LsaEnumerateLogonSessions
和LsaGetLogonSessionData
的结果,遗憾的是它的结果相同,所列出的会话都没有预期的域名。以下是来自LsaEnumerateLogonSessions
:
Session: 0 User: MARK *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 2/6/2014 7:34:17 AM
Session: 0 User: ADMINISTRATOR *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 2/4/2014 7:47:11 AM
Session: 0 User: ADMINISTRATOR *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 1/27/2014 3:27:33 PM
Session: 0 User: MCMFILE2$ *** Domain: NTLAN_1 *** Login Type: (5) Service *** Login Time: 1/16/2014 3:52:46 PM
Session: 0 User: MCM-LR9-YE91K$ *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 2/6/2014 10:52:40 AM
Session: 0 User: MARK *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 2/6/2014 10:19:39 AM
Session: 0 User: ADMINISTRATOR *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 1/20/2014 9:57:57 AM
Session: 0 User: ANONYMOUS LOGON *** Domain: NT AUTHORITY *** Login Type: (3) Network *** Login Time: 1/16/2014 3:53:19 PM
Session: 1 User: ADMINISTRATOR *** Domain: NTLAN_1 *** Login Type: (2) Interactive *** Login Time: 1/16/2014 3:53:11 PM
Session: 0 User: LOCAL SERVICE *** Domain: NT AUTHORITY *** Login Type: (5) Service *** Login Time: 1/16/2014 3:52:46 PM
Session: 0 User: MARK *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 2/6/2014 10:52:40 AM
Session: 1 User: ADMINISTRATOR *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 2/6/2014 10:52:38 AM
Session: 0 User: MARK *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 2/6/2014 10:19:39 AM
Session: 0 User: ADMINISTRATOR *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 1/18/2014 6:20:25 PM
Session: 0 User: ANONYMOUS LOGON *** Domain: NT AUTHORITY *** Login Type: (3) Network *** Login Time: 1/16/2014 3:53:19 PM
Session: 0 User: CVSMANAGER_USER *** Domain: MCMFILE2 *** Login Type: (5) Service *** Login Time: 1/16/2014 3:53:09 PM
Session: 0 User: MCM-LR9-YE91K$ *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 2/6/2014 10:52:40 AM
Session: 0 User: MARK *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 2/6/2014 10:19:39 AM
Session: 0 User: DefaultAppPool *** Domain: IIS APPPOOL *** Login Type: (5) Service *** Login Time: 2/6/2014 8:42:47 AM
Session: 0 User: ADMINISTRATOR *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 2/4/2014 2:40:40 PM
Session: 0 User: IUSR *** Domain: NT AUTHORITY *** Login Type: (5) Service *** Login Time: 1/16/2014 3:53:09 PM
Session: 0 User: MCMFILE2$ *** Domain: NTLAN_1 *** Login Type: (0) 0 *** Login Time: 1/16/2014 3:52:44 PM
有问题的会话有会话ID = 1.从列表中,它显示域名为NTLAN_1而不是实际域。
现在,我在我的桌面应用程序中发现了一些奇怪的东西,我相信在找到这个问题的解决方案时有一个关键的部分,但我不知道该怎么做。
现在我的桌面应用程序是用.NET编写的,所以我尝试直接运行应用程序来获取用户名和域名。现在有趣的是,如果我使用本机GetUserNameEx
函数并将NameUserPrincipal
作为NameFormat传递,我可以获得正确的用户名/域组合。但是,这是有趣的部分,当我尝试通过调用Environment
使用Environment.UserDomainName
类获取域名时,我得到了NTLAN_1的罪魁祸首。请注意,托管和非托管调用都是由同一个应用程序在同一次运行中完成的。
我之前没有遇到过这样的问题,现在看来我有更多的用户报告了同样的问题而且开始真的很烦我。
答案 0 :(得分:2)
我终于找到了问题,有问题的域实际上是UPN后缀,而不是域名。我仍然认为这是来自MS的错误,因为WTSQuerySessionInformation
和LsaEnumerateLogonSessions
都应该返回域名而不是UPN后缀。
我能够通过依赖帐户SID而不是用户名/域组合来解决问题,幸运的是,无论是使用实际域名还是后缀查询,SID都是相同的。
感谢Harry Johnston
关于SID的惊人评论。
答案 1 :(得分:0)
作为评论太大了......希望这有用......
那么......服务是否有效地查询本地或远程服务器?
以下摘自this MSDN link which describes the WTSQuerySessionInformation function
“仅在本地服务器上获取会话信息时指定WTS_CURRENT_SESSION。如果在远程服务器上查询会话信息时指定了WTS_CURRENT_SESSION,则返回的会话信息将不一致。请勿使用返回的数据。”
这是您传入的SessionId参数。此外:
“要在远程桌面服务运行时检索当前会话的会话ID,请调用WTSQuerySessionInformation并为SessionId参数指定WTS_CURRENT_SESSION,为WTSInfoClass参数指定WTSSessionId。会话ID将在ppBuffer参数中返回。”
更新:尝试使用WTSEnumerateSessionsEx通过扩展结构获取更多会话信息 WTS_SESSION_INFO_1,其本身包含域名...
“pDomainName - 指向以null结尾的字符串的指针,该字符串包含登录到会话的用户的域名。如果没有用户登录到该会话,则该字符串包含NULL。 “
如果用户正在影响另一个人,则不确定它是什么。