C# 如何确定我的Windows域中的计算机是否为;主动的;

C# 如何确定我的Windows域中的计算机是否为;主动的;,c#,exception,networking,dns,ping,C#,Exception,Networking,Dns,Ping,我正在尝试编写一种方法来确定我域中的哪些计算机处于“非活动”状态。我能够使其正常工作的唯一方法是尝试通过以下方式获取计算机的IP地址: Dns.GetHostAddresses(computerName) 如果计算机处于“非活动”状态,它会抛出一个System.Net.Sockets.SocketException,然后我可以捕获该计算机并将其添加到我的非活动计算机数据表中。这种方法的问题是速度慢得令人痛苦。在我的Windows域中,有500台计算机,大约300台处于“非活动”状态,用这种方法对

我正在尝试编写一种方法来确定我域中的哪些计算机处于“非活动”状态。我能够使其正常工作的唯一方法是尝试通过以下方式获取计算机的IP地址:

Dns.GetHostAddresses(computerName)

如果计算机处于“非活动”状态,它会抛出一个
System.Net.Sockets.SocketException
,然后我可以捕获该计算机并将其添加到我的非活动计算机数据表中。这种方法的问题是速度慢得令人痛苦。在我的Windows域中,有500台计算机,大约300台处于“非活动”状态,用这种方法对它们进行排序几乎需要30分钟。有人对如何判断在我的Windows域中注册的计算机是否处于活动状态有什么建议吗

我还尝试通过ping列表中的所有计算机来实现这一点,但在尝试ping“非活动”计算机时,会抛出一个
System.Net.NetworkInformation.PingException
,我必须以相同的方式捕获和处理它。这也给了我这个过程将近30分钟的运行时间

这是我的密码

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();
        }
编辑:

我尝试使用多个线程来完成任务,但等待时间仍然很长(我现在正在运行它,但它仍然没有完成)

下面是我如何实现它的,改进性能的建议

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 );
            }
List inactiveComputerNames=new List();
foreach(searcher.FindAll()中的SearchResult)
{
新线程(委托()
{
if(result.GetDirectoryEntry().Name.StartsWith(“CN=))
{
字符串computerName=result.GetDirectoryEntry().Name.Remove(0,“CN=.Length”);
尝试
{
Dns.GetHostAddresses(计算机名);
}
捕获(SocketException)
{
不活动的computerName.Add(computerName);
}
}
}).Start();
}
foreach(InactiveComputerName中的字符串computerName)
{
DataRow newRow=\u InactiveComputers.newRow();
newRow[“ComputerName”]=计算机名称;
newRow[“CustomerName”]=CustomerName;
_不活动的computers.Rows.Add(newRow);
}

我有一个类似的要求,我想扫描网络中的IP地址,以确定正在使用的地址

我做了几个假设,首先,Ping不会在大多数设备上被阻止,其次,我们只处理特定范围的地址,例如192.168.x.x

这不是最干净的代码,只是一个快速而肮脏的示例,但下面将作为控制台应用程序运行,并演示如何将线程与Ping结合使用的基本原则

希望有帮助

你好,韦恩

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

    }
} 
使用系统;
Net系统;
使用System.Net.NetworkInformation;
使用System.Collections.Generic;
使用System.Net.Sockets;
使用System.Threading.Tasks;
名称空间网络
{
班级计划
{
私有静态int_超时=120;
私有静态int nextLine=0;
公共静态void Main(字符串[]args)
{
Console.WriteLine(“NetworkPing!”);
//检查是否提供了任何命令行参数
如果(args.Length>0)
{
//解析参数
foreach(args中的字符串arg)
{
开关(arg[1].ToString())
{
案例“?”:
{
//显示帮助主题
显示帮助();
}
打破
案例“t”:
{
//改变时间表
_Timeout=Int32.Parse(GetParameter(arg));
WriteLine(“Ping超时设置为{0}ms”,_超时);
}
打破
}    
}
}
DateTime startTime=DateTime.Now;
IPAddress[]地址S2=GetAllunicastAddresss();
foreach(地址中的IP地址2)
{
控制台。写线(“”);
WriteLine(“本地IP地址:{0}”,Adres);
WriteLine(“扫描从{0}.1到{0}.254的IP,等待结果…”,网络地址(Adres));
nextLine=Console.CursorTop;
Task[]tasks=新任务[254];
for(int i=0;i!=254;i++)
{
//计算ping的IP地址
字符串ipAddressToPing=网络地址(Adres)+“+(i+1);
//ping地址并检查响应
tasks[i]=Task.Factory.StartNew(()=>PingAddress(ipAddressToPing));
}
//阻止,直到所有任务完成。
Task.WaitAll(任务);
}
TimeSpan ts=日期时间.Now-startTime;
控制台。写线(“”);
WriteLine(“扫描在{0}秒内完成,按任意键继续…”,ts.seconds);
Console.ReadKey();
}
私有静态字符串GetParameter(字符串参数)
{
返回参数.Substring(参数.LastIndexOf(“:”)+1);
}
publicstaticvoiddisplayhelp()
{
Console.WriteLine(“用法:PingNetwork[/?]或[-?][-t:Timeout]”);
控制台。写线(“”);
安慰
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 );
                        }
                    }
                }
            }
            );