简体   繁体   English

如何确定Windows域中的计算机是否处于“活动”状态

[英]How to determine if a computer in my Windows Domain is “active”

I'm trying to write a method that will determine which computers in my domain are "inactive." 我正在尝试编写一种方法,以确定我域中的哪些计算机“不活动”。 The only way I have been able to get this to work is by trying to get the IP address of the computer by using: 我能够使它起作用的唯一方法是尝试使用以下方法获取计算机的IP地址:

Dns.GetHostAddresses( computerName )

If the computer is "inactive" it throws a System.Net.Sockets.SocketException which I am then able to catch and add that computer to my DataTable of inactive computers. 如果计算机“处于非活动状态”,则会引发System.Net.Sockets.SocketException ,然后我可以捕获该计算机并将其添加到非活动计算机的DataTable中。 The problem with this method is that it is PAINFULLY slow. 这种方法的问题在于它的速度缓慢。 Going through my Windows domain with 500 computers about 300 are "inactive" and it takes almost 30 minutes to sort them by this method. 在我的Windows域中有500台计算机,大约300台计算机处于“非活动状态”,通过这种方法对它们进行排序大约需要30分钟。 Does anyone have a suggestion on how to tell if a computer registered in my Windows domain is active? 有人对如何确定在我的Windows域中注册的计算机是否处于活动状态有建议吗?

I have also tried to do this by pinging all the computers in my list, but when trying to ping an "inactive" computer is throws a System.Net.NetworkInformation.PingException which I have to catch and handle the same way. 我也尝试通过ping列表中的所有计算机来执行此操作,但是当尝试ping“不活动”的计算机时会抛出System.Net.NetworkInformation.PingException ,我必须以相同的方式进行捕获和处理。 This also gives me a nearly 30 minute run-time for this process. 这也为我提供了将近30分钟的运行时间。

Here is my code. 这是我的代码。

public void findInactiveComputers( string customerName, string domain )
        {
            DirectoryEntry entry = new DirectoryEntry( domain );
            DirectorySearcher searcher = new DirectorySearcher( entry );
            searcher.Filter = ("(objectClass=computer)");
            searcher.SizeLimit = int.MaxValue;
            searcher.PageSize = int.MaxValue;

            // Removes the inactive computers from the DataTable that associated with the customer.
            if( _InactiveComputers.Rows.Count != 0 )
            {
                _InactiveComputers.AsEnumerable().Where( cust => cust["CustomerName"].ToString()
                    .Equals( customerName, StringComparison.InvariantCultureIgnoreCase ) )
                    .ToList().ForEach( comp => comp.Delete() );
            }

            foreach( SearchResult result in searcher.FindAll() )
            {
                if( result.GetDirectoryEntry().Name.StartsWith( "CN=" ) )
                {
                    string computerName = result.GetDirectoryEntry().Name.Remove( 0, "CN=".Length );

                    try
                    { 
                        Dns.GetHostAddresses( computerName );
                    }

                    catch( SocketException )
                    {
                        DataRow newRow = _InactiveComputers.NewRow();
                        newRow["ComputerName"] = computerName;
                        newRow["CustomerName"] = customerName;
                        _InactiveComputers.Rows.Add( newRow );
                    }
                }
            }

            Properties.Settings.Default.InvalidComputers = _InactiveComputers;
            Properties.Settings.Default.Save();
        }

EDIT: 编辑:

I tried to use multiple threads to accomplish my task, but the wait time is still very long (I'm running it now and it still hasn't completed). 我尝试使用多个线程来完成任务,但是等待时间仍然很长(我现在正在运行它,但它尚未完成)。

Here's how I implemented it, suggestions to improve performance? 这是我的实施方式,建议如何提高性能?

List<string> inactiveComputerNames = new List<string>();

            foreach( SearchResult result in searcher.FindAll() )
            {
                new Thread( delegate()
                    {
                        if( result.GetDirectoryEntry().Name.StartsWith( "CN=" ) )
                        {
                            string computerName = result.GetDirectoryEntry().Name.Remove( 0, "CN=".Length );

                            try
                            {
                                Dns.GetHostAddresses( computerName );
                            }

                            catch( SocketException )
                            {
                                inactiveComputerNames.Add( computerName );
                            }
                        }
                    } ).Start();
            }

            foreach( string computerName in inactiveComputerNames )
            {
                DataRow newRow = _InactiveComputers.NewRow();
                newRow["ComputerName"] = computerName;
                newRow["CustomerName"] = customerName;
                _InactiveComputers.Rows.Add( newRow );
            }

I had a similar requirement in that I wanted to scan a network for IP addresses to determine the addresses in use. 我有一个类似的要求,因为我想扫描网络中的IP地址以确定正在使用的地址。

I made several assumptions, firstly that the Ping would not be blocked on the majority of equipment, secondly that we were only dealing with a specific range of addresses EG 192.168.xx 我做了几个假设,首先,Ping不会在大多数设备上被阻止,其次,我们只处理特定范围的地址EG 192.168.xx

It's not the cleanest of code, just a quick and dirty example but the following will run as a console app and demonstrates the basic principles of how you could use threading in conjunction with Ping. 它不是最干净的代码,只是一个简单而肮脏的示例,但是以下内容将作为控制台应用程序运行,并演示了如何将线程与Ping结合使用的基本原理。

Hope it helps? 希望能帮助到你?

Kind Regards, Wayne 亲切的问候,韦恩

using System;
using System.Net;
using System.Net.NetworkInformation;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Threading.Tasks;

namespace NetworkPing
{
    class Program
    {

        private static int _Timeout = 120;
        private static int nextLine = 0;

        public static void Main(string[] args)
        {
            Console.WriteLine("NetworkPing!");

            //check if any command line arguments have been supplied
            if (args.Length > 0)
            {
                //parse the the arguments
                foreach ( string arg in args)
                {
                    switch( arg[1].ToString() )
                    {
                        case "?":
                            {
                                //display help topic
                                DisplayHelp();
                            }
                        break;

                        case "t":
                            {
                                //change the timout
                                _Timeout = Int32.Parse( GetParameter(arg) );
                                Console.WriteLine("Ping timeout set to {0}ms", _Timeout);
                            }
                        break;
                    }    
                }
            }


            DateTime startTime = DateTime.Now;

            IPAddress[] Adresses2 = GetAllUnicastAddresses();
            foreach (IPAddress Adres in Adresses2)
            {
                Console.WriteLine("");
                Console.WriteLine("Local IP Address: {0}", Adres);
                Console.WriteLine("Scanning IP from {0}.1 to {0}.254, awaiting results...", NetworkAddress(Adres) );

                nextLine = Console.CursorTop;

                Task[] tasks = new Task[254];

                for (int i = 0; i != 254; i++)
                {
                    //calculate the IP address for the ping
                    string ipAddressToPing = NetworkAddress( Adres ) + "." + (i+1);
                    //ping the address and check the response
                    tasks[ i ] = Task.Factory.StartNew( () => PingAddress(ipAddressToPing) );
                }

                //Block until all tasks complete.
                Task.WaitAll(tasks);

            }

            TimeSpan ts = DateTime.Now - startTime;
            Console.WriteLine("");            
            Console.WriteLine("Scan complete in {0} seconds, Press any key to continue...", ts.Seconds);
            Console.ReadKey();
        }

        private static string GetParameter( string Argument )
        {
            return Argument.Substring( Argument.LastIndexOf(":") +1);
        }

        public static void DisplayHelp()
        {
            Console.WriteLine("Usage: PingNetwork [/?] or [-?] [-t:Timeout]");
            Console.WriteLine("");
            Console.WriteLine("  {0,-12} {1}","/?","Display these usage instructions");
            Console.WriteLine("  {0,-12} {1}","-?","Display these usage instructions");
            Console.WriteLine("  {0,-12} {1}","-t:timeout","Changes the default timout from 120ms");
            Console.WriteLine("");
        }

        public static IPAddress[] GetAllUnicastAddresses()
        {
            // This works on both Mono and .NET , but there is a difference: it also
            // includes the LocalLoopBack so we need to filter that one out
            List<IPAddress> Addresses = new List<IPAddress>();
            // Obtain a reference to all network interfaces in the machine
            NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
            foreach (NetworkInterface adapter in adapters)
            {
                IPInterfaceProperties properties = adapter.GetIPProperties();
                foreach (IPAddressInformation uniCast in properties.UnicastAddresses)
                {
                    // Ignore loop-back, IPv6 and link-local
                    if (!IPAddress.IsLoopback(uniCast.Address) && uniCast.Address.AddressFamily!= AddressFamily.InterNetworkV6 && !uniCast.Address.ToString().StartsWith("169.254.") )
                        Addresses.Add(uniCast.Address);
                }

            }
            return Addresses.ToArray();
        }

        private static void PingAddress( string IPAddress )
        {
            Ping pingSender = new Ping ();
            PingOptions options = new PingOptions ();

            // Use the default Ttl value which is 128,
            // but change the fragmentation behavior.
            options.DontFragment = true;

            // Create a buffer of 32 bytes of data to be transmitted.
            string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
            byte[] buffer = System.Text.Encoding.ASCII.GetBytes (data);

            PingReply reply = pingSender.Send(IPAddress, _Timeout, buffer, options);

            if (reply.Status == IPStatus.Success)
            {
                   //set the cursor to the next line
                Console.CursorTop = nextLine;
                //        
                Console.WriteLine( IPAddress + " :OK");
                //
                nextLine++;
            }
        }


        private static string NetworkAddress( IPAddress Address )
        {
            string ipAddress = Address.ToString();
            return ipAddress.Substring( 0, ipAddress.LastIndexOf(".") );
        }

        private static string LastOctet( IPAddress Address )
        {
            string ipAddress = Address.ToString();
            return ipAddress.Substring( ipAddress.LastIndexOf(".") );
        }

        private static int _cursorX;
        private static int _cursorY;

        private static void GetCursor()
        {
            _cursorX = Console.CursorLeft;
            _cursorY = Console.CursorTop;
        }

        private static void SetCursor()
        {
            Console.CursorLeft = _cursorX;
            Console.CursorTop = _cursorY;
        }

    }
} 

Figured out this issue...Finally! 解决了这个问题...最后! I used a Parallel.ForEach Loop and it solved all my problems. 我使用了Parallel.ForEach循环,它解决了我所有的问题。 I had to use locking around the access to the List as sixlettervariables suggested. 我建议按照Sixletter变量建议使用对列表访问的锁定。 Worked great! 很棒!

SearchResultCollection results = searcher.FindAll();

            List<string> inactiveComputerNames = new List<string>();

            object threadLock = new object();

            Parallel.ForEach( results.OfType<SearchResult>(), result =>
            {
                if( result.GetDirectoryEntry().Name.StartsWith( "CN=" ) )
                {
                    string computerName = result.GetDirectoryEntry().Name.Remove( 0, "CN=".Length );

                    try
                    {
                        Dns.GetHostAddresses( computerName );
                    }

                    catch( SocketException )
                    {
                        lock( threadLock )
                        {
                            inactiveComputerNames.Add( computerName );
                        }
                    }
                }
            }
            );

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

相关问题 如何在Windows 10中获取计算机域名 - How do I get the computer domain name in Windows 10 如何确定我的计算机正在使用哪个网络适配器? - How do I determine which network adapter my computer is using? 如何确定Windows标识是对应于本地用户还是域用户? - How can I determine if a Windows Identity corresponds to a local or a domain user? 如何确定我的应用程序是否处于活动状态(有焦点) - How to determine whether my application is active (has focus) 如何确定我的域计算机上是否安装了特定的应用程序 - How to determine whether a specific application is installed on my domain computers 如何确定服务器上是否已安装“ Active Directory域服务”角色 - How to determine if the “Active Directory Domain Services” role has been installed on a server 使用C#和Powershell从不属于域的计算机访问Active Directory - Accessing Active Directory From a Computer Not Part of the Domain With C# and Powershell c#Active Directory身份验证用户(如果计算机不在域中) - c# Active Directory Authentication User if Computer not in domain 如何判断计算机是否属于C#中特定Windows域的一部分 - How can I tell if a computer is a part of a specific Windows domain in C# 在Windows 7计算机上远程确定交互式/活动用户 - Remotely determine interactive/active user on Windows 7 machine
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM