If you want to find MS SQL Servers which are available in a network, there are two different ways you can use for searching the network for available Sql Servers.

1 – There is a class in the .NET Framework which name is SqlDataSourceEnumerator in the System.Data.Sql namespace. We can use that class, and get the sql servers easly:

DataTable sqls = SqlDataSourceEnumerator.Instance.GetDataSources();

In this method we can only get the Sql Server machines on a network. There is also another method to get list of SQL Servers on a network. Also this second method can also be used to search for some other type of servers too. Here is the second method;

2 – We can use NetServerEnum function in the netapi32.dll. The following code demonstrates us how we can find SQL Servers in a network…

public class NativeMethods
{
    public const uint ERROR_SUCCESS = 0;
    public const uint ERROR_MORE_DATA = 234;    

    [DllImport("netapi32.dll", EntryPoint = "NetServerEnum")]
    public static extern int NetServerEnum(
            [MarshalAs(UnmanagedType.LPWStr)]
            string servername,
            int level,
            out IntPtr bufptr,
            int prefmaxlen,
            ref int entriesread,
            ref int totalentries,
            SV_101_TYPES servertype,
            [MarshalAs(UnmanagedType.LPWStr)]
            string domain,
            int resume_handle);     

    [DllImport("netapi32.dll", EntryPoint = "NetApiBufferFree")]
    public static extern int NetApiBufferFree(IntPtr buffer);

    [StructLayout(LayoutKind.Sequential)]
    public struct SERVER_INFO_101
    {
        [MarshalAs(UnmanagedType.U4)]
        public PLATFORM_ID sv101_platform_id;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string sv101_name;
        [MarshalAs(UnmanagedType.U4)]
        public uint sv101_version_major;
        [MarshalAs(UnmanagedType.U4)]
        public uint sv101_version_minor;
        [MarshalAs(UnmanagedType.U4)]
        public SV_101_TYPES sv101_type;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string sv101_comment;
    }

    public enum SV_101_TYPES : uint
    {
        SV_TYPE_WORKSTATION = 0x00000001,
        SV_TYPE_SERVER = 0x00000002,
        SV_TYPE_SQLSERVER = 0x00000004,
        SV_TYPE_DOMAIN_CTRL = 0x00000008,
        SV_TYPE_DOMAIN_BAKCTRL = 0x00000010,
        SV_TYPE_TIME_SOURCE = 0x00000020,
        SV_TYPE_AFP = 0x00000040,
        SV_TYPE_NOVELL = 0x00000080,
        SV_TYPE_DOMAIN_MEMBER = 0x00000100,
        SV_TYPE_PRINTQ_SERVER = 0x00000200,
        SV_TYPE_DIALIN_SERVER = 0x00000400,
        SV_TYPE_XENIX_SERVER = 0x00000800,
        SV_TYPE_SERVER_UNIX = 0x00000800,
        SV_TYPE_NT = 0x00001000,
        SV_TYPE_WFW = 0x00002000,
        SV_TYPE_SERVER_MFPN = 0x00004000,
        SV_TYPE_SERVER_NT = 0x00008000,
        SV_TYPE_POTENTIAL_BROWSER = 0x00010000,
        SV_TYPE_BACKUP_BROWSER = 0x00020000,
        SV_TYPE_MASTER_BROWSER = 0x00040000,
        SV_TYPE_DOMAIN_MASTER = 0x00080000,
        SV_TYPE_SERVER_OSF = 0x00100000,
        SV_TYPE_SERVER_VMS = 0x00200000,
        SV_TYPE_WINDOWS = 0x00400000,
        SV_TYPE_DFS = 0x00800000,
        SV_TYPE_CLUSTER_NT = 0x01000000,
        SV_TYPE_TERMINALSERVER = 0x02000000,
        SV_TYPE_CLUSTER_VS_NT = 0x04000000,
        SV_TYPE_DCE = 0x10000000,
        SV_TYPE_ALTERNATE_XPORT = 0x20000000,
        SV_TYPE_LOCAL_LIST_ONLY = 0x40000000,
        SV_TYPE_DOMAIN_ENUM = 0x80000000,
        SV_TYPE_ALL = 0xFFFFFFFF
    }

    public enum PLATFORM_ID : uint
    {
        PLATFORM_ID_DOS = 300,
        PLATFORM_ID_OS2 = 400,
        PLATFORM_ID_NT = 500,
        PLATFORM_ID_OSF = 600,
        PLATFORM_ID_VMS = 700
    }
}

We can use the following native methods as follows;

public List<string> GetServers()
{
    var servers = new List<string>();
    int readed = 0;
    int total = 0;

    do
    {
        IntPtr buffer;
        NativeMethods.SERVER_INFO_101 server;
        int retVal = NativeMethods.NetServerEnum(null, 101, out buffer, -1,
                                ref readed, ref total,
                                NativeMethods.SV_101_TYPES.SV_TYPE_SQLSERVER, null, 0);

        if (retVal == NativeMethods.ERROR_SUCCESS ||
                    retVal == NativeMethods.ERROR_MORE_DATA ||
                    readed > 0)
        {
            int handle = buffer.ToInt32();
            for (int i = 0; i < readed; i++)
            {
                server = (NativeMethods.SERVER_INFO_101)Marshal.PtrToStructure(
                                    new IntPtr(handle),
                                    typeof(NativeMethods.SERVER_INFO_101));

                handle += Marshal.SizeOf(server);
                servers.Add(server.sv101_name);
            }
        }
        NativeMethods.NetApiBufferFree(buffer);
    }
    while (readed < total && readed != 0);

    return servers;
}

In this example if you call the GetServers method, this will return you the list of the SQL Servers on the network.

Not only for the SQL Servers also you can find any other group of computers by using NetServerEnum method. The SV_101_TYPES enumeration identifies the type of the computer, which you can search for. If you use another value of this enum in GetServers method, you will get the computers list of that kind.

For example; if you are searching for Teminal Servers on the network, use SV_TYPE_TERMINALSERVER while calling NetServerEnum method in the GetServers method. This will returns you the Terminal Servers on the network.

Share: