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:
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. 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. Does anyone have a suggestion on how to tell if a computer registered in my Windows domain is active?
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. This also gives me a nearly 30 minute run-time for this process.
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 );
}
Figured out this issue…Finally! I used a
Parallel.ForEachLoop and it solved all my problems. I had to use locking around the access to the List as sixlettervariables suggested. Worked great!