0

我正在开发需要监视 Windows 会话更改并在特定用户登录时自动启动应用程序的服务应用程序。

这是它的工作原理,我有一个文件,其中包含以用户主体名称格式 (user@domain.LOCAL) 存储的 Windows 用户名列表。我的服务将监视任何会话更改,并在其中一个用户登录后采取某些操作。

List<string> _UsersList;
 object _sessionCheckLock = new object();
        void OnCheckSession(int nSessionId, bool bIsLoggIn)
        {
            lock(_sessionCheckLock)
            {
                try
                {
                    string sUserName = string.Empty;
                    string sDomain = string.Empty;

                    IntPtr pUserName = IntPtr.Zero;
                    uint nBytesReturned = 0;
                    if (WTSQuerySessionInformation(IntPtr.Zero, (uint)nSessionId, WTS_INFO_CLASS.WTSUserName, out pUserName, out nBytesReturned) && (pUserName != IntPtr.Zero))
                    {
                        sUserName = Marshal.PtrToStringAnsi(pUserName);

                        WTSFreeMemory(pUserName);

                        IntPtr pDomain = IntPtr.Zero;
                        if(WTSQuerySessionInformation(IntPtr.Zero, (uint)nSessionId, WTS_INFO_CLASS.WTSDomainName, out pDomain, out nBytesReturned) && (pDomain != IntPtr.Zero))
                        {
                            sDomain = Marshal.PtrToStringAnsi(pDomain);
                            WTSFreeMemory(pDomain);
                        }
                        else
                        {

                        }

                        if (!string.IsNullOrEmpty(sUserName))
                        {
                          if(!string.IsNullOrEmpty(sDomain)
                          {
                              sUserName += "@" + sDomain;
                          }

                            foreach(string username in _UsersList)
                            {
                               if(string.Compare(sUsername, username, true)==0)
                               {
                                //Do a couple of things
                                return;
                               }
                            }

                        }
                    }
                    else
                    {
                        return;
                    }
                }
                catch (System.Exception ex)
                {

                }
            }
        }

上面的代码是每当引发新的登录事件时我调用的函数。_UsersList 是一个字符串列表,其中包含允许服务使用的所有用户名。这里的问题是,WTSQuerySessionInformation使用 with 时WTS_INFO_CLASS.WTSDomainName不会返回域的全名,因此比较失败。例如,如果用户列表中存在名为 (username@DOMAIN.LOCAL) 的用户名并登录,则在查询会话的域名,它只返回 (DOMAIN) 而没有 .LOCAL 附录。我需要找到一种方法来获取完整的域名以匹配我列表中的域名。

有人可以帮忙吗

4

3 回答 3

2

查看 Cassia.Net,这是一个非常有用的。

您可以下载源代码,我将它用于一个项目,我必须让所有登录到服务器的用户。

cassia .NET Windows 终端服务/远程桌面服务库

http://code.google.com/p/cassia/

希望有帮助

于 2012-11-30T22:43:36.910 回答
1

红蛇,卡西亚真的有帮助吗?我和你有同样的问题,但是 Cassia 似乎在WTSQuerySessionInformation下面使用了相同的调用,所以我仍然只是得到了短域名。

页面上,我找到了对函数的引用,该DsGetDcName函数可用于使用WTSQuerySessionInformation给我的短域名获取 FQDN。这是对我有用的示例:

std::wstring GetSessionDomainName(DWORD sessionId)
{
    std::wstring domainName;
    LPWSTR buffer = NULL;
    DWORD bufferSize = 0;

    if(WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSDomainName, &buffer, &bufferSize))
    {
        PDOMAIN_CONTROLLER_INFOW domainControllerInfo = NULL;
        DWORD retVal = DsGetDcNameW(NULL, buffer, NULL, NULL, DS_IS_FLAT_NAME | DS_RETURN_DNS_NAME, &domainControllerInfo);
        if (retVal == 0)
            domainName = domainControllerInfo->DnsForestName;

        WTSFreeMemory(buffer);
        NetApiBufferFree(domainControllerInfo);
    }

    return domainName;
}
于 2013-05-17T17:29:37.033 回答
1

WTDomainName 显示了用户所属的域——我找不到任何明确的文档,但我认为它获取的是 netBios 名称,而不是 FQDN。你应该可以使用两个环境变量 USERDNSDOMAIN USERDOMAIN 来保存这些值。

您还可以使用 ADSI 进行更详细的查找,看看这里的线程

但这一切都说明了,除非你有一个非常复杂的森林结构,用户从树中的许多不同域登录......将转换硬编码到你的应用程序中可能会快得多。它们不是经常变化的东西,从新域登录的用户也应该很少见。

于 2012-11-28T17:51:08.207 回答