Howto get just servers from Active Directory

  • Thread starter Thread starter CoolBreeze812
  • Start date Start date
C

CoolBreeze812

Hello,

I'm using the following code to get the list of computers joined to a
domain in Active Directory and using the System.DirectoryServices
namespace.

DirectoryEntry dirEntry = new DirectoryEntry("LDAP://spencenet.com");
DirectorySearcher dirSearch = new
DirectorySearcher(dirEntry);
dirSearch.Filter = "(objectClass=Computer)";
foreach (SearchResult sr in dirSearch.FindAll())
{
try
{

listBox1.Items.Add(sr.GetDirectoryEntry().Name.ToString().Substring(3));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "LDAP: Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
listBox1.SelectedIndex = 0;
}

The problem is that it returns all computers, both servers and
workstations. I would like to limit this to only servers being listed
in the listbox. I have tried objectClass=Server, but nothing was
returned and I haven't been able to find any other attribute that would
list only the servers in the domain.

I have a test domain setup and tried the code both on a Windows 2003
server and an XP workstation that is joined to the domain with the
objectClass=Server, both did not populate the listbox with only the
listing of the Windows 2003 server. FYI, I have the Windows 2003 server
configured with a role of Domain Controller and DNS Server only.

Does anyone know how I can retrieve only servers within an Active
Directory Domain?

Thanks,
-- Lance
 
CoolBreeze812 said:
Hello,

I'm using the following code to get the list of computers joined to a
domain in Active Directory and using the System.DirectoryServices
namespace.

DirectoryEntry dirEntry = new DirectoryEntry("LDAP://spencenet.com");
DirectorySearcher dirSearch = new
DirectorySearcher(dirEntry);
dirSearch.Filter = "(objectClass=Computer)";
foreach (SearchResult sr in dirSearch.FindAll())
{
try
{

listBox1.Items.Add(sr.GetDirectoryEntry().Name.ToString().Substring(3));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "LDAP: Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
listBox1.SelectedIndex = 0;
}

The problem is that it returns all computers, both servers and
workstations. I would like to limit this to only servers being listed
in the listbox. I have tried objectClass=Server, but nothing was
returned and I haven't been able to find any other attribute that would
list only the servers in the domain.

I have a test domain setup and tried the code both on a Windows 2003
server and an XP workstation that is joined to the domain with the
objectClass=Server, both did not populate the listbox with only the
listing of the Windows 2003 server. FYI, I have the Windows 2003 server
configured with a role of Domain Controller and DNS Server only.

Does anyone know how I can retrieve only servers within an Active
Directory Domain?

Thanks,
-- Lance

The directory only knows "computer" as object type, that means that there is no way to make
a distinction between a "workstation" and a "server". All you can do to make a distinction
between both is by querying for the OS version installed on the "computer" another option is
to put servers in a distinct OU from the "workstations".

Willy.
 
Thanks for the reply. Using the code I presented, how would I query
the OS version?

-- Lance
 
CoolBreeze812 said:
Thanks for the reply. Using the code I presented, how would I query
the OS version?

-- Lance

Supposed all computers are contained in computers (as per default), you can simply do
something like this:

// bind to and get at the "computers" container
using (DirectoryEntry computers = new
DirectoryEntry("LDAP://spencenet.com/cn=computers");
{
foreach(DirectoryEntry comp in computers.Children)
{
Console.WriteLine(comp.Properties["operatingsystem"].Value);
}
}

this should return something like:
Windows Server 2003
Windows XP Professional
Windows VistaT Ultimate

another option is to get the operatingsystemversion property, this will return something
like:
5.2 (3790)
5.1 (2600)
6.0 (6000)

obviously you'l have to parse the string to determine the computer type, in which case it's
preferable to parse the version string.

Willy.
 
Again thank you very much for your help.
-- Lance

CoolBreeze812 said:
Thanks for the reply. Using the code I presented, how would I query
the OS version?
-- LanceSupposed all computers are contained in computers (as per default), you can simply do
something like this:

// bind to and get at the "computers" container
using (DirectoryEntry computers = new
DirectoryEntry("LDAP://spencenet.com/cn=computers");
{
foreach(DirectoryEntry comp in computers.Children)
{
Console.WriteLine(comp.Properties["operatingsystem"].Value);
}
}

this should return something like:
Windows Server 2003
Windows XP Professional
Windows VistaT Ultimate

another option is to get the operatingsystemversion property, this will return something
like:
5.2 (3790)
5.1 (2600)
6.0 (6000)

obviously you'l have to parse the string to determine the computer type, in which case it's
preferable to parse the version string.

Willy.
 
Again thank you Willy for your help. I tried your example and
unfortunately couldn't get it to work. What I'd really like to do is
adjust the following code to accomplish what I'm after, but I am having
a hard time doing so. Do you have any pointers on how I might be able
to do this. As you can see I'm a newbie, so I welcome any refactoring
suggestions as well.

private void wsrMainForm_Load(object sender, EventArgs e)
{
int versionCompareResult;

DirectoryEntry dirEntry = new
DirectoryEntry("LDAP://spencenet.com");
DirectorySearcher dirSearch = new
DirectorySearcher(dirEntry);
ManagementObjectSearcher serverQuery = new
ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem");
ManagementObjectCollection serverQueryCollection =
serverQuery.Get();
dirSearch.Filter = "(objectClass=computer)";

foreach (ManagementObject mo in serverQueryCollection)
{
versionCompareResult =
String.Compare(mo["version"].ToString(), "5.1 (2600)");
mo["version"].ToString();
if (versionCompareResult > 0)
{
try
{
foreach (SearchResult sr in
dirSearch.FindAll())
{

computersListBox.Items.Add(sr.GetDirectoryEntry().Name.ToString().Substring(3));
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "LDAP: Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
computersListBox.SelectedIndex = 0;
}
}
}


CoolBreeze812 said:
Thanks for the reply. Using the code I presented, how would I query
the OS version?
-- LanceSupposed all computers are contained in computers (as per default), you can simply do
something like this:

// bind to and get at the "computers" container
using (DirectoryEntry computers = new
DirectoryEntry("LDAP://spencenet.com/cn=computers");
{
foreach(DirectoryEntry comp in computers.Children)
{
Console.WriteLine(comp.Properties["operatingsystem"].Value);
}
}

this should return something like:
Windows Server 2003
Windows XP Professional
Windows VistaT Ultimate

another option is to get the operatingsystemversion property, this will return something
like:
5.2 (3790)
5.1 (2600)
6.0 (6000)

obviously you'l have to parse the string to determine the computer type, in which case it's
preferable to parse the version string.

Willy.
 
CoolBreeze812 said:
Again thank you Willy for your help. I tried your example and
unfortunately couldn't get it to work. What I'd really like to do is
adjust the following code to accomplish what I'm after, but I am having
a hard time doing so. Do you have any pointers on how I might be able
to do this. As you can see I'm a newbie, so I welcome any refactoring
suggestions as well.

private void wsrMainForm_Load(object sender, EventArgs e)
{
int versionCompareResult;

DirectoryEntry dirEntry = new
DirectoryEntry("LDAP://spencenet.com");
DirectorySearcher dirSearch = new
DirectorySearcher(dirEntry);
ManagementObjectSearcher serverQuery = new
ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem");
ManagementObjectCollection serverQueryCollection =
serverQuery.Get();
dirSearch.Filter = "(objectClass=computer)";

foreach (ManagementObject mo in serverQueryCollection)
{
versionCompareResult =
String.Compare(mo["version"].ToString(), "5.1 (2600)");
mo["version"].ToString();
if (versionCompareResult > 0)
{
try
{
foreach (SearchResult sr in
dirSearch.FindAll())
{

computersListBox.Items.Add(sr.GetDirectoryEntry().Name.ToString().Substring(3));
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "LDAP: Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
computersListBox.SelectedIndex = 0;
}
}
}


You don't have to use System.Management to get at the OS version, this is all stored in the
AD.

You ca do something like this, if you like to bind to the root of the AD....
...
using (DirectoryEntry root = new DirectoryEntry("LDAP://spencenet.com");
{
DirectorySearcher dirSearch = new DirectorySearcher(root);
dirSearch.Filter = "(objectClass=Computer)";
foreach (SearchResult sr in dirSearch.FindAll())
{
// enumerate each computer entry in the directory.
using (DirectoryEntry computer = sr.GetDirectoryEntry())
{
// fetch osversion
string version =
computer.Properties["operatingsystemversion"].Value.Substring(0, 3);
switch (version)
{
case "4.0":
// NT4 Server or WKST, here you'll have to parse
"operatingsystem" property !
// fill list ...
break;
case "5.0":
// Windows 2000 Server or WKST, here you'll have to parse
"operatingsystem" property !
...
break;
case "5.1":
// Windows XP, this is a WKST OS
...
break;
case "5.2":
// Windows 2003 Server, this is a Server OS
...
break;
case "6.0":
// Vista, this is a WKST OS
...
break;
default:
// Unknown
break;

}
}
}
}

But, it's faster to bind to the root of the container if possible, for instance the
"computers" container contains all computers in a domain (default), you can change the code
into this:

using (DirectoryEntry root = new DirectoryEntry("LDAP://spencenet.com, cn=computers");
{
..

Willy.
 
Thanks for the sample. I believe I'm on the right track now.

-- Lance

Again thank you Willy for your help. I tried your example and
unfortunately couldn't get it to work. What I'd really like to do is
adjust the following code to accomplish what I'm after, but I am having
a hard time doing so. Do you have any pointers on how I might be able
to do this. As you can see I'm a newbie, so I welcome any refactoring
suggestions as well.
private void wsrMainForm_Load(object sender, EventArgs e)
{
int versionCompareResult;
DirectoryEntry dirEntry = new
DirectoryEntry("LDAP://spencenet.com");
DirectorySearcher dirSearch = new
DirectorySearcher(dirEntry);
ManagementObjectSearcher serverQuery = new
ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem");
ManagementObjectCollection serverQueryCollection =
serverQuery.Get();
dirSearch.Filter = "(objectClass=computer)";
foreach (ManagementObject mo in serverQueryCollection)
{
versionCompareResult =
String.Compare(mo["version"].ToString(), "5.1 (2600)");
mo["version"].ToString();
if (versionCompareResult > 0)
{
try
{
foreach (SearchResult sr in
dirSearch.FindAll())
{
computersListBox.Items.Add(sr.GetDirectoryEntry().Name.ToString().Substring(3));
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "LDAP: Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
computersListBox.SelectedIndex = 0;
}
}
}You don't have to use System.Management to get at the OS version, this is all stored in the
AD.

You ca do something like this, if you like to bind to the root of the AD....
...
using (DirectoryEntry root = new DirectoryEntry("LDAP://spencenet.com");
{
DirectorySearcher dirSearch = new DirectorySearcher(root);
dirSearch.Filter = "(objectClass=Computer)";
foreach (SearchResult sr in dirSearch.FindAll())
{
// enumerate each computer entry in the directory.
using (DirectoryEntry computer = sr.GetDirectoryEntry())
{
// fetch osversion
string version =
computer.Properties["operatingsystemversion"].Value.Substring(0, 3);
switch (version)
{
case "4.0":
// NT4 Server or WKST, here you'll have to parse
"operatingsystem" property !
// fill list ...
break;
case "5.0":
// Windows 2000 Server or WKST, here you'll have to parse
"operatingsystem" property !
...
break;
case "5.1":
// Windows XP, this is a WKST OS
...
break;
case "5.2":
// Windows 2003 Server, this is a Server OS
...
break;
case "6.0":
// Vista, this is a WKST OS
...
break;
default:
// Unknown
break;

}
}
}
}

But, it's faster to bind to the root of the container if possible, for instance the
"computers" container contains all computers in a domain (default), you can change the code
into this:

using (DirectoryEntry root = new DirectoryEntry("LDAP://spencenet.com, cn=computers");
{
..

Willy.
 
Back
Top