繁体   English   中英

域网C#在线AD用户列表

[英]List of online AD users in domain network C#

有一个域网络与连接的计算机。

需要一个代码来显示现在连接到它的Active Directory用户列表(使用它们/远程连接)。

类似于任务管理器中的“用户”选项卡,仅适用于域网络。


我试图用WMI做到这一点。 Win32_LogonSessionWin32_LoggedOnUserWin32_Account

原理是这样的:

从活动的Win32_LogonSession中剔除LogonType = 2、10 è 11。
通过Win32_LoggedOnUser中的LogonId获取名称和域,在Win32_Account中搜索(清除系统会话)(下面会有代码,也许有人会派上用场)

但是我遇到了一个问题:触发事件Session_onEnd远不是100%的情况, LogOff好像根本没有记录,或者记录不正确。

结果,我得到很多用户连接到的“挂起”会话,或者在他们登录时创建新会话。在这方面分析 Windows 事件日志也没有提供任何有用的信息。 LogOff仍然不正确)


那么,如果我可以连接到计算机并从中获取所有信息,那么如何提取 - 它现在是否在使用以及谁在使用它?

using System;
using System.Collections.Generic;
using System.Data;
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
using System.Linq;
using System.Management;
using System.Net;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace UserManager
{
    public partial class LogOnSession : Form
    {
        List<LogOnSessionR> SessionsList = new List<LogOnSessionR>();
        List<LoggedOnUser> LoggedList = new List<LoggedOnUser>();
        List<PC> CompList = new List<PC>();
        public LogOnSession()
        {
            InitializeComponent();
        }

        private void LogOnSession_Load(object sender, EventArgs e)
        {
            if (Form1.SelfRef != null)
            {
                CBDomain.Items.Add("All Forest");
                foreach (object a in Form1.SelfRef.CBDomain.Items)
                {
                    CBDomain.Items.Add(a);
                }
                CBDomain.SelectedIndex = Form1.SelfRef.CBDomain.SelectedIndex;
            }

            GetComputersInDomain(CBDomain.SelectedIndex);
            CBComputers.SelectedIndex = 0;
        }
        private void CBDomain_SelectedIndexChanged(object sender, EventArgs e)
        {
            LogOnListView.Items.Clear();
            GetComputersInDomain(CBDomain.SelectedIndex);
        }
        public void GetComputersInDomain(int I)
        {
            CompList.Clear();
            CBComputers.Items.Clear();
            if (I == 0)
            {
                DirectoryEntry de = new DirectoryEntry();
                DirectorySearcher myADSearcher = new DirectorySearcher(de);
                myADSearcher.Filter = "(&(objectClass=computer))";

                foreach (SearchResult sr in myADSearcher.FindAll())
                {
                    PC pc = new PC();
                    pc.Name = removeCN(sr.GetDirectoryEntry().Name);
                    pc.IP = getPCIP(pc.Name);
                    CompList.Add(pc);
                }
            }
            else
            {
                DirectoryEntry de = new DirectoryEntry("LDAP://" + Form1.ListDomain[I-1].Name);
                DirectorySearcher myADSearcher = new DirectorySearcher(de);
                myADSearcher.Filter = "(&(objectClass=computer))";

                foreach (SearchResult sr in myADSearcher.FindAll())
                {
                    PC pc = new PC();
                    pc.Name = removeCN(sr.GetDirectoryEntry().Name);
                    pc.IP = getPCIP(pc.Name);
                    CompList.Add(pc);
                }
            }
            
            CBComputers.Items.Add("All");
            foreach (PC pc in CompList)
            {
                CBComputers.Items.Add(pc.Name);
            }
        }



        public string removeCN(string str)
        {
            if (str.Contains("CN="))
            {
                return str.Replace("CN=", "");
            }
            else
            {
                return str;
            }
        }
        public string getPCIP(string hostName)
        {
            IPHostEntry hostEntry;

            hostEntry = Dns.GetHostEntry(hostName);

            if (hostEntry.AddressList.Length > 0)
            {
                return hostEntry.AddressList[0].ToString();
                //you might get more than one ip for a hostname since 
                //DNS supports more than one record
            }
            return null;
        }


        private void RefreshL_Click(object sender, EventArgs e)
        {
            ViewResult(getInfo());
        }
        public void ViewResult(List<LogonUser> results)
        {

            LogOnListView.Items.Clear();
            if (results.Count == 0) { return; }
            int i = 0;
            foreach (LogonUser result in results)
            {

                LogOnListView.Items.Add(i.ToString());
                LogOnListView.Items[i].SubItems.Add(result.SamAccountName);
                LogOnListView.Items[i].SubItems.Add(result.FullName);
                LogOnListView.Items[i].SubItems.Add(result.Computer);
                LogOnListView.Items[i].SubItems.Add(result.Domain);
                LogOnListView.Items[i].SubItems.Add(result.StartTime.ToLocalTime().ToString());
                LogOnListView.Items[i].SubItems.Add(cAD.LastLastLogon(getDN(result.SamAccountName)).ToLocalTime().ToString());
                LogOnListView.Items[i].SubItems.Add(cAD.LastLastLogoff(getDN(result.SamAccountName)).ToLocalTime().ToString());
                i++;
            }

        }

        private string getDN(string samAccountName)
        {
            DirectoryEntry myADEntry = new DirectoryEntry();
            DirectorySearcher myADSearcher = new DirectorySearcher(myADEntry);
            myADSearcher.Filter = "(&(objectClass=user)(sAMAccountName=" + samAccountName + ")(!(objectClass=computer)))";
            return myADSearcher.FindOne().GetDirectoryEntry().Properties["distinguishedName"].Value.ToString();
        }

        private List<LogonUser> getInfo()
        {
            List<LogonUser> LogonUserList = new List<LogonUser>();
            ConnectionOptions options;
            options = new ConnectionOptions();

            //options.Username = "administrator";
            //options.Password = "Parol-Admin";
            options.EnablePrivileges = true;
            options.Impersonation = ImpersonationLevel.Impersonate;

            if (CBComputers.SelectedIndex == 0)
            {
                foreach (PC pc in CompList)
                {
                    if (pc.Name == Environment.MachineName)
                    {
                        LogonUserList.AddRange(getLogonUserList(pc, options, LocalWMIRequestLogOnSession(), LocalWMIRequestLoggedOnUser()));
                    }
                    else
                    {
                        LogonUserList.AddRange(getLogonUserList(pc, options, WMIRequestLogOnSession(pc.IP, options), WMIRequestLoggedOnUser(pc.IP, options)));
                    }
                }
            }
            else
            {
                PC pc = CompList[CBComputers.SelectedIndex - 1];
                if (pc.Name == Environment.MachineName)
                {
                    LogonUserList.AddRange(getLogonUserList(pc, options, LocalWMIRequestLogOnSession(), LocalWMIRequestLoggedOnUser()));
                }
                else
                {
                    LogonUserList.AddRange(getLogonUserList(pc, options, WMIRequestLogOnSession(pc.IP, options), WMIRequestLoggedOnUser(pc.IP, options)));
                }
            }
            return LogonUserList;
        }



        private LogonUser FindInDomainController(PC pc, ConnectionOptions options, LoggedOnUser lou, LogOnSessionR losr)
        {
            try
            {
                List<PC> Controllers = new List<PC>();
                if (CBDomain.SelectedIndex == 0)
                {
                    foreach (GlobalCatalog contr in Form1.DsDomain.Forest.GlobalCatalogs)
                    {
                        PC Con = new PC();
                        Con.Name = contr.Name;
                        Con.IP = contr.IPAddress;
                        Controllers.Add(Con);
                    }
                }
                else
                {
                    foreach (DomainController contr in Form1.ListDomain[CBDomain.SelectedIndex - 1].DomainControllers)
                    {
                        PC Con = new PC();
                        Con.Name = contr.Name;
                        Con.IP = contr.IPAddress;
                        Controllers.Add(Con);
                    }

                }
                LogonUser getlg;

                foreach (PC Controller in Controllers)
                {
                    ManagementScope scope;
                    if (Controller.Name == Environment.MachineName)
                    {
                        scope = new ManagementScope("\\root\\cimv2");
                    }
                    else
                    {
                        scope = new ManagementScope("\\\\" + Controller.IP + "\\root\\cimv2", options);
                        scope.Connect(); // 
                    }

                    String queryString = "SELECT * FROM Win32_UserAccount WHERE Domain=\"" + getDomain(lou.Antecedent) + "\" AND Name=\"" + getsAmAccountName(lou.Antecedent) + "\"";

                    ObjectQuery query;
                    query = new ObjectQuery(queryString);

                    ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
                    var Temp = searcher.Get()
                        .Cast<ManagementObject>()
                        .Select(mo => new
                        {
                            Name = Convert.ToString(mo["Name"]),
                            FullName = Convert.ToString(mo["FullName"]),
                            AccountType = Convert.ToUInt32(mo["AccountType"]),
                            Caption = Convert.ToString(mo["Caption"]),
                            Description = Convert.ToString(mo["Description"]),
                            Disabled = Convert.ToBoolean(mo["Disabled"]),
                            Domain = Convert.ToString(mo["Domain"]),
                            InstallDate = Convert.ToDateTime(mo["InstallDate"]),
                            LocalAccount = Convert.ToBoolean(mo["LocalAccount"]),
                            Lockout = Convert.ToBoolean(mo["Lockout"]),
                            PasswordChangeable = Convert.ToBoolean(mo["PasswordChangeable"]),
                            PasswordExpires = Convert.ToBoolean(mo["PasswordExpires"]),
                            PasswordRequired = Convert.ToBoolean(mo["PasswordRequired"]),
                            SID = Convert.ToString(mo["SID"]),
                            SIDType = Convert.ToByte(mo["SIDType"]),
                            Status = Convert.ToString(mo["Status"])
                        }
                        ).ToList();
                    if (Temp.Count == 0) { continue; }
                   // if (Temp.Count > 1) { throw new Exception("Найденно " + Temp.Count + " одинаковых пользователя"); }

                    getlg = new LogonUser()
                    {
                        AuthenticationPackage = losr.AuthenticationPackage,
                        Name = Temp[0].Name,
                        Domain = Temp[0].Domain,
                        Caption = Temp[0].Caption,
                        Description = Temp[0].Description,
                        InstallDate = Temp[0].InstallDate,
                        LogonId = losr.LogonId,
                        LogonType = losr.LogonType,
                        StartTime = losr.StartTime,
                        Status = Temp[0].Status,
                        Computer = pc.Name,
                        SamAccountName = getsAmAccountName(lou.Antecedent),
                        FullName = Temp[0].FullName,
                        AccountType = Temp[0].AccountType,
                        Enabled = !Temp[0].Disabled,
                        LocalAccount = Temp[0].LocalAccount,
                        Lockout = Temp[0].Lockout,
                        PasswordChangeable = Temp[0].PasswordChangeable,
                        PasswordExpires = Temp[0].PasswordExpires,
                        PasswordRequired = Temp[0].PasswordRequired,
                        SID = Temp[0].SID,
                        SIDType = Temp[0].SIDType
                    };

                    return getlg;
                }

                return null;

            }
            catch
            {

            }
            return null;
        }

        public List<LogOnSessionR> LocalWMIRequestLogOnSession()
        {
            List<LogOnSessionR> ReqList = new List<LogOnSessionR>();

            ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2",
                   "SELECT * FROM Win32_LogonSession WHERE LogonType = '2' OR LogonType = '10' OR LogonType = '11'");
            var Temp = searcher.Get()
                .Cast<ManagementObject>()
                .Select(mo => new
                {
                    AuthenticationPackage = Convert.ToString(mo["AuthenticationPackage"]),
                    Name = Convert.ToString(mo["Name"]),
                    Caption = Convert.ToString(mo["Caption"]),
                    Description = Convert.ToString(mo["Description"]),
                    InstallDate = (mo["InstallDate"] == null ? Convert.ToDateTime(mo["InstallDate"]) : ManagementDateTimeConverter.ToDateTime(mo["InstallDate"].ToString())),
                    LogonId = Convert.ToString(mo["LogonId"]),
                    LogonType = Convert.ToUInt32(mo["LogonType"]),
                    StartTime = (mo["StartTime"] == null ? Convert.ToDateTime(mo["StartTime"]) : ManagementDateTimeConverter.ToDateTime(mo["StartTime"].ToString())),
                    Status = Convert.ToString(mo["Status"])
                }
                ).ToList();

            foreach (var obj in Temp)
            {
                LogOnSessionR req = new LogOnSessionR();
                req.AuthenticationPackage = obj.AuthenticationPackage;
                req.Name = obj.Name;
                req.Caption = obj.Caption;
                req.Description = obj.Description;
                req.InstallDate = obj.InstallDate;
                req.LogonId = obj.LogonId;
                req.LogonType = obj.LogonType;
                req.StartTime = obj.StartTime;
                req.Status = obj.Status;
                ReqList.Add(req);
            }


            return ReqList;
        }
        public List<LoggedOnUser> LocalWMIRequestLoggedOnUser()
        {
            List<LoggedOnUser> ReqList = new List<LoggedOnUser>();

            ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2",
                   "SELECT * FROM Win32_LoggedOnUser");
            var Temp = searcher.Get()
                .Cast<ManagementObject>()
                .Select(mo => new
                {
                    Antecedent = Convert.ToString(mo["Antecedent"]),
                    Dependent = Convert.ToString(mo["Dependent"])
                }
                ).ToList();

            foreach (var obj in Temp)
            {
                LoggedOnUser req = new LoggedOnUser();
                req.Antecedent = obj.Antecedent;
                req.Dependent = obj.Dependent;
                ReqList.Add(req);
            }


            return ReqList;
        }




        private string getLogonId(string dependent)
        {
            var start = "LogonId=\"";
            var end = "\"";
            var regEx = new Regex(String.Format("{0}(.*){1}", Regex.Escape(start), Regex.Escape(end)));
            var match = regEx.Match(dependent);
            return match.Groups[1].Value;
            // "\\\\.\\root\\cimv2:Win32_LogonSession.LogonId=\"997\""
        }
        private string getDomain(string antecedent)
        {
            var start = "Domain=\"";
            var end = "\",";
            var regEx = new Regex(String.Format("{0}(.*){1}", Regex.Escape(start), Regex.Escape(end)));
            var match = regEx.Match(antecedent);
            return match.Groups[1].Value;
            // "\\\\.\\root\\cimv2:Win32_Account.Domain=\"LAB\" AND Name=\"Administrator\""
        }
        private string getsAmAccountName(string antecedent)
        {
            var start = "Name=\"";
            var end = "\"";
            var regEx = new Regex(String.Format("{0}(.*){1}", Regex.Escape(start), Regex.Escape(end)));
            var match = regEx.Match(antecedent);
            return match.Groups[1].Value;
            // 
        }




        private List<LogonUser> getLogonUserList(PC pc, ConnectionOptions options, List<LogOnSessionR> sessionsList, List<LoggedOnUser> loggedList)
        {
            List<LogonUser> getList = new List<LogonUser>();

            foreach (LoggedOnUser lou in loggedList)
            {
                foreach(LogOnSessionR losr in sessionsList)
                {
                    if (losr.LogonId == getLogonId(lou.Dependent))
                    {
                        LogonUser temp = FindInDomainController(pc, options, lou, losr);
                        if (temp != null)
                        {
                            getList.Add(temp);
                        }
                    }
                }
            }
            return getList;
        }
        public List<LogOnSessionR> WMIRequestLogOnSession(string ip, ConnectionOptions options)
        {
            List<LogOnSessionR> ReqList = new List<LogOnSessionR>();

            try
            {
                ManagementScope scope;
                scope = new ManagementScope("\\\\" + ip + "\\root\\cimv2", options);
                scope.Connect();

                String queryString = "SELECT * FROM Win32_LogonSession WHERE LogonType = '2' OR LogonType = '10' OR LogonType = '11'";

                ObjectQuery query;
                query = new ObjectQuery(queryString);

                ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
                var Temp = searcher.Get()
                    .Cast<ManagementObject>()
                    .Select(mo => new
                    {
                        AuthenticationPackage = Convert.ToString(mo["AuthenticationPackage"]),
                        Name = Convert.ToString(mo["Name"]),
                        Caption = Convert.ToString(mo["Caption"]),
                        Description = Convert.ToString(mo["Description"]),
                        InstallDate = (mo["InstallDate"] == null ? Convert.ToDateTime(mo["InstallDate"]) : ManagementDateTimeConverter.ToDateTime(mo["InstallDate"].ToString())),
                        LogonId = Convert.ToString(mo["LogonId"]),
                        LogonType = Convert.ToUInt32(mo["LogonType"]),
                        StartTime = (mo["StartTime"] == null ? Convert.ToDateTime(mo["StartTime"]) : ManagementDateTimeConverter.ToDateTime(mo["StartTime"].ToString())),
                        Status = Convert.ToString(mo["Status"])
                    }
                    ).ToList();

                foreach (var obj in Temp)
                {
                    LogOnSessionR req = new LogOnSessionR();
                    req.AuthenticationPackage = obj.AuthenticationPackage;
                    req.Name = obj.Name;
                    req.Caption = obj.Caption;
                    req.Description = obj.Description;
                    req.InstallDate = obj.InstallDate;
                    req.LogonId = obj.LogonId;
                    req.LogonType = obj.LogonType;
                    req.StartTime = obj.StartTime;
                    req.Status = obj.Status;
                    ReqList.Add(req);
                }
                return ReqList;
            }
            catch
            {

            }


            return new List<LogOnSessionR>();
        }
        public List<LoggedOnUser> WMIRequestLoggedOnUser(string ip, ConnectionOptions options)
        {
            List<LoggedOnUser> ReqList = new List<LoggedOnUser>();

            try
            {
                ManagementScope scope;
                scope = new ManagementScope("\\\\" + ip + "\\root\\cimv2", options);
                scope.Connect();

                String queryString = "SELECT * FROM Win32_LoggedOnUser";

                ObjectQuery query;
                query = new ObjectQuery(queryString);

                ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
                var Temp = searcher.Get()
                    .Cast<ManagementObject>()
                    .Select(mo => new
                    {
                        Antecedent = Convert.ToString(mo["Antecedent"]),
                        Dependent = Convert.ToString(mo["Dependent"])
                    }
                    ).ToList();

                foreach (var obj in Temp)
                {
                    LoggedOnUser req = new LoggedOnUser();
                    req.Antecedent = obj.Antecedent;
                    req.Dependent = obj.Dependent;
                    ReqList.Add(req);
                }
                return ReqList;
            }
            catch
            {
                
            }


            return new List<LoggedOnUser>();
        }



        private void label2_Click(object sender, EventArgs e)
        {

        }
    }
    public class PC
    {
        public string Name { get; set; }
        public string IP { get; set; }

    }
    public class LoggedOnUser
    {
        public string Antecedent { get; set; }
        public string Dependent  { get; set; }

    }
    public class LogOnSessionR
    {
        public string AuthenticationPackage { get; set; }
        public string Name { get; set; }
        public string Caption { get; set; }
        public string Description { get; set; }
        public System.DateTime InstallDate { get; set; }
        public string LogonId { get; set; }
        public UInt32 LogonType { get; set; }
        public System.DateTime StartTime { get; set; }
        public string Status { get; set; }

    }
    public class LogonUser
    {
        public string AuthenticationPackage { get; set; }
        public string Name { get; set; }
        public string Domain { get; set; }
        public string Caption { get; set; }
        public string Description { get; set; }
        public System.DateTime InstallDate { get; set; }
        public string LogonId { get; set; }
        public UInt32 LogonType { get; set; }
        public System.DateTime StartTime { get; set; }
        public string Status { get; set; }
        public string Computer { get; set; }
        public string SamAccountName { get; set; }
        public string FullName { get; set; }
        public uint AccountType { get; set; }
        public bool? Enabled { get; set; }
        public bool LocalAccount { get; set; }
        public bool Lockout { get; set; }
        public bool PasswordChangeable { get; set; }
        public bool PasswordExpires { get; set; }
        public bool PasswordRequired { get; set; }
        public string SID { get; set; }
        public byte SIDType { get; set; }
    }
}

如果您可以连接到域网络中的任何计算机并从中获取任何信息 - 这是安全问题,必须解决。

首先,您必须了解您的解决方案的安全问题。 任何您无法连接的计算机都可能受到黑客的攻击。 在我的经历中也有类似的先例。

因此,如果您需要从域网络中的计算机或服务器获取任何信息 - 您必须在每台计算机和服务器上安装一些代理,以获取其内部数据 state。 该代理将通过您的规则集监视计算机/服务器,并将信息发送到某个数据库或收集系统。

Microsoft 拥有具有此体系结构和用途的 System Center Operations Manager。 您可以开发自己的代理,或使用 powershell 脚本 + windows 调度程序从计算机收集任何数据。

不要在域网络中实施您的解决方案 - 这很糟糕。 更好的解决方案是检查域中包含哪些计算机以及哪些计算机具有来自监视数据库的代理。 并在它们尚不存在的计算机上安装代理。

任何在域对象(例如,所有计算机)上具有大量权限的用户帐户或组 - 都是必须解决的安全问题。

如果您想获得任何登录用户 - 您可以检查进程 explorer.exe - 哪个用户启动它。

所以,如果你使用 powershell 脚本作为代理来收集数据,你可以运行

query user

例如,它将显示:

user |seance    |ID |Staus  |Idle time | logon time     |
-----|----------|---|-------|----------|----------------|
user1|rdp-tcp   |2  |Active | .        |12/07/2020 10:20|

然后您可以将此数据存储在您的数据库或其他存储中。

如果你想开发一些代理,你可以使用Windows API,System.Runtime.InteropServices,像这样,因为你的代理可以访问这个API。

此外,您可以获取通过登录计算机的用户

    foreach (System.Management.ManagementObject Process in Processes.Get())
{
    if (Process["ExecutablePath"] != null && 
        System.IO.Path.GetFileName(Process["ExecutablePath"].ToString()).ToLower() == "explorer.exe" )
    {
        string[] OwnerInfo = new string[2];
        Process.InvokeMethod("GetOwner", (object[])OwnerInfo);

        Console.WriteLine(string.Format("Windows Logged-in Interactive UserName={0}", OwnerInfo[0]));

        break;
    }
}

每个用户都启动进程 explorer.exe,并拥有它。

此外,您不需要存储任何 sp

暂无
暂无

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

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