简体   繁体   English

从会话ID获取完整的Windows域名

[英]Get the full windows domain name from a session id

I am working on service application that needs to monitor windows session changes and automatically start an application if a specific user logged on to. 我正在研究需要监视Windows会话更改并在特定用户登录后自动启动应用程序的服务应用程序。

Here is how it works, I have a file with a list of Windows usernames stored in a user principal name format (user@domain.LOCAL). 这是它的工作方式,我有一个文件,其中包含以用户主体名称格式(user@domain.LOCAL)存储的Windows用户名列表。 My service will monitor any session changes and will take certain actions once one of those users gets logged on. 我的服务将监视任何会话更改,并在其中一个用户登录后采取某些措施。

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)
                {

                }
            }
        }

The above code is the function I call whenever a new logon event is raised. 上面的代码是每当引发新的登录事件时我调用的函数。 The _UsersList is a list of strings that contains all the usernames that the service is allowed to work with. _UsersList是一个字符串列表,其中包含允许该服务使用的所有用户名。 The problem here is that WTSQuerySessionInformation when used with WTS_INFO_CLASS.WTSDomainName does not return the full name of the domain and therefore the comparison fails.For example if a username called (username@DOMAIN.LOCAL) exists in the list of user and logs on, when querying for the domain name of the session, it returns only (DOMAIN) without the .LOCAL appendix. 这里的问题是WTSQuerySessionInformationWTS_INFO_CLASS.WTSDomainName使用时不返回域的全名,因此比较失败。例如,如果用户列表中存在一个名为(username@DOMAIN.LOCAL)的用户名并登录,查询会话的域名时,它仅返回(DOMAIN),而没有.LOCAL附录。 I need to find a way to get the full domain name to match the one in my list. 我需要找到一种方法来获取完整的域名以匹配列表中的域名。

Can someone help please 有人可以帮忙吗

Look into Cassia.Net, this is a very useful. 查看Cassia.Net,这是非常有用的。

You can download the source code, i used this for a project where i had to get all the users that were logged on to a server. 您可以下载源代码,我将其用于一个项目,在该项目中,我必须获取所有已登录到服务器的用户。

cassia .NET Windows Terminal Services / Remote Desktop Services Library 决明子.NET Windows终端服务/远程桌面服务库

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

hope that helps 希望能有所帮助

WTSDomainName shows the domain a user is a member of-- I cannot find any explicit documentation, but I would assume that it is getting the netBios name, not the FQDN. WTsmainName显示用户所属的域-我找不到任何明确的文档,但是我认为它获取的是netBios名称,而不是FQDN。 You should be able to use the two environmental variable USERDNSDOMAIN USERDOMAIN hold these values. 您应该能够使用USERDNSDOMAIN和USERDOMAIN这两个环境变量来保存这些值。

You can also use ADSI to do a more detailed lookup, have a look at the thread here 您也可以使用ADSI进行更详细的查找,在此处查看线程

But this all said, unless you have an INCREDIBLY complex forest structure, with users logging in from many different domains in the tree... it will probably be much faster to just hard-code the conversions into your app. 但这一切都说明了,除非您拥有一个令人难以置信的复杂林结构,并且用户从树中的许多不同域中登录,否则...将转换硬编码到您的应用中可能会更快。 They are not something that often changes, and users logging in from a new domain should also be rare. 它们并不是经常更改的东西,从新域登录的用户也应该很少。

Red Serpent, did Cassia really help? 红蛇,决明子真的有帮助吗? I had the same problem as you, but Cassia seems to use the same WTSQuerySessionInformation call underneath, so I was still only getting the short domain name. 我遇到了与您相同的问题,但是Cassia似乎在下面使用了相同的WTSQuerySessionInformation调用,因此我仍然只得到了简短的域名。

On this page I found a reference to the DsGetDcName function which I was able to use to get the FQDN using the short domain name that WTSQuerySessionInformation gave me. 页面上,我找到了对DsGetDcName函数的引用,我可以使用该函数使用WTSQuerySessionInformation给我的短域名获取FQDN。 Here's my example that works for me: 这是适合我的示例:

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM