Introduction
A Windows class library for selecting networked computers.
Background
While having authored several Windows Forms apps, I've frequently needed to browse the network specifically for selecting a computer, however there is no managed method to accomplish this. I was inspired by Michael Potter's Finding SQL Servers on the Network article, so I decided to take it a little further and allow more granular control of the types of computers one can select.
Enumerating Computers
The first thing we have to do is define the function which will perform this task for us. NetServerEnum
is located in the NetApi32.dll library.
[DllImport("Netapi32", CharSet=CharSet.Unicode)]
private static extern int NetServerEnum(
string servername,
int level,
out IntPtr bufptr,
int prefmaxlen,
out int entriesread,
out int totalentries,
uint servertype,
[MarshalAs(UnmanagedType.LPWStr)]
string domain,
IntPtr resume_handle );
The third parameter of NetServerEnum
will populate a structure containing information about the computers it finds. With the exception of sv101_platform_id & sv101_type, these values are exposed as public properties in the NetworkComputers
struct.
[StructLayoutAttribute(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
internal struct SERVER_INFO_101
{
public int sv101_platform_id;
public string sv101_name;
public int sv101_version_major;
public int sv101_version_minor;
public int sv101_type;
public string sv101_comment;
}
To get our list, we simply call one of the CompEnum
constructors and pass it one of the ServerType
values
ce = new CompEnum(CompEnum.ServerType.SV_TYPE_DOMAIN_CTRL |
CompEnum.ServerType.SV_TYPE_MASTER_BROWSER)
or it's equivalent bit-mapped value (
GetServerTypeValues
performs this step for us)
private void GetServerTypeValues(object sender, System.EventArgs e)
{
int filterVal = 0x00;
bool itemsChecked = false;
foreach (CheckBox cb in groupBoxServerTypes.Controls)
{
if (cb.Checked)
{
filterVal += Int32.Parse((string)cb.Tag,
System.Globalization.NumberStyles.HexNumber);
itemsChecked = true;
}
}
checkBoxAll.Enabled = !itemsChecked;
DisplayComputerTypes((uint)filterVal);
}
Now we can enumerate through our collection of computers.
internal void DisplayComputerTypes(uint serverType)
{
Cursor.Current = Cursors.WaitCursor;
lbComputers.Items.Clear();
ce = new CompEnum(serverType, cbDomainList.SelectedItem.ToString());
int numServer = ce.Length;
if (ce.LastError.Length == 0)
{
IEnumerator enumerator = ce.GetEnumerator();
int i = 0;
while (enumerator.MoveNext())
{
lbComputers.Items.Add(ce[i].Name);
i++;
}
}
...
Enumerating SQL Servers Using SQL-DMO
Short for SQL Server Distributed Management Objects, SQL-DMO is a far more reliable way to retrieve the names of SQL Servers on your network. My code first performs a check to see if SQL-DMO is possible, otherwise it uses the regular NetServerEnum
API.
private void GetSqlServersUsingSQLDMO(object sender, System.EventArgs e)
{
SQLDMO.Application app = new SQLDMO.ApplicationClass();
SQLDMO.NameList nameList = app.ListAvailableSQLServers();
string srvName = "";
_sqlServerList = new string[nameList.Count];
for (int i=0; i<nameList.Count; i++)
{
srvName = nameList.Item(i + 1);
_sqlServerList[i] = srvName;
}
}
ListAvailableSQLServers()
returns a NameList
object that enumerates SQL Server names. From here we use the Item
method of NameList
to retrieve the actual server name. That's all there is to it.
Sample Usage
CompPicker cp = new CompPicker();
if (cp.ShowDialog(this) == DialogResult.OK)
MessageBox.Show(this, cp.SelectedComputerName);
Extending
To extend the library to fit your needs, simply add or remove checkboxes in the groupBoxServerTypes group box and place their tag values equal to one of the ServerType bitmap values. These values are originally defined in
LMServer.h and can also be found in the
CompEnum
class.
Performance Issues
Performance is hampered in a non-domain environment, presumably because there is no browse master defined? The same holds true when browsing in a different domain than the one you are currently in.
Compatibility
Since the NetServerEnum
WinAPI is only available for Windows NT or greater, it will not work on Win9x machines.
History
- Version 1.0 - 06.01.2004 - First release version.
- Version 1.1 - 07.15.2004 - Utilize SQL-DMO for enumerating SQL Servers, if available.