Click here to Skip to main content
Click here to Skip to main content

Retreiving a list of network computer names using C#

By , 26 Oct 2006
 

Demo screen shot

Note: I only have one computer in my home network, so only one computer is shown in the screenshot above. It does work with many computers.

Introduction

This submission was actually written as part of a University project for my BSc., where I was using .NET Remoting and I had a server application and a client application, and I needed the client application to be able to connect to a given server application.

The problem was, I did not know what machine name the server was running on, in fact I wanted this to be flexible, and selectable by the user. So after I searched the .NET documentation on MSDN and couldn't find any managed classes which dealt with network computers or anything like that, I consulted a C++ programming friend of mine (Nick Cross, you know who you are), who mentioned the NetApi32.dll and the NetServerEnum method. After I looked at the NetApi32.dll documentation, it looked as though it seemed to provide a list network computer names. Lovely.

Eureka I thought, but then I had to trawl the MSDN documentation for the relevant structures and methods I need to consume the NetApi32.dll unmanaged methods within my C# (managed) code.

So this article is really a culmination of research and pain, that I had, trying to get my head around how to consume the NetApi32 C++ DLL within C#. It was not fun, but I got there in the end.

I hope this article helps someone out, as it helped me.

Using the code

The demo project provided actually contains all the source code needed. The demo is based on a simple Windows Forms application written in Visual Studio 2005. The code works the same in .NET v1.1.

So now onto the code. The main class is called NetworkBrowser which really does all the work. The demo form is a throw away, which is simply used to demo the code submission.

using System;
using System.Runtime.InteropServices;
using System.Security;
using System.Collections;
using System.Windows.Forms;

namespace ListNetworkComputers
{
    #region NetworkBrowser CLASS
    /// <summary>
    /// Provides a mechanism for supplying
    // a list of all PC names in the local network.
    /// This collection of PC names is used in the form 
    /// 
    
    
    /// This class makes use of a DllImport instruction.
    /// The purpose of which is as follows:
    /// When a DllImport declaration is made
    /// in managed code (C#) it is a call to a legacy
    /// unmanaged code module, normally
    /// a C++ Dynamic Link Library. These C++ Dll's are
    /// usually part of the operating system API,
    /// or some other vendors API, and must be 
    /// used to carry out operations that are not
    /// native within the managed code C# framework. 
    /// This is fairly normal within the windows world.
    /// The only thing that needs careful consideration
    /// is the construction of the correct type of STRUCTS,
    /// object pointers, and attribute markers,
    /// which all contribute to making the link
    /// between managed (C#) and unmanaged code (C++)
    /// more seamless
    /// 
    
    /// This class makes use of the following Dll calls
    /// <list type="bullet">
    /// <item>
    /// <description> Netapi32.dll : NetServerEnum,
    /// The NetServerEnum function lists all servers
    /// of the specified type that are visible in
    /// a domain. For example, an application can call 
    /// NetServerEnum to list all domain controllers
    /// only or all SQL servers only.
    /// You can combine bit masks to list several
    /// types. For example, a value of 0x00000003 
    /// combines the bit masks for SV_TYPE_WORKSTATION
    /// (0x00000001) and SV_TYPE_SERVER (0x00000002).
    /// </description>
    /// </item>
    /// <item>
    /// <description> Netapi32.dll : NetApiBufferFree,
    /// The NetApiBufferFree function frees 
    /// the memory that the NetApiBufferAllocate
    /// function allocates. Call NetApiBufferFree 
    /// to free the memory that other network
    /// management functions return.</description>
    /// </item>
    /// </list>
    /// </summary>
    public sealed class NetworkBrowser
    {
        #region Dll Imports

        //declare the Netapi32 : NetServerEnum method import
        [DllImport("Netapi32", CharSet = CharSet.Auto, 
        SetLastError = true),
        SuppressUnmanagedCodeSecurityAttribute]

        /// <summary>
        /// Netapi32.dll : The NetServerEnum function lists all servers
        /// of the specified type that are
        /// visible in a domain. For example, an 
        /// application can call NetServerEnum
        /// to list all domain controllers only
        /// or all SQL servers only.
        /// You can combine bit masks to list
        /// several types. For example, a value 
        /// of 0x00000003  combines the bit
        /// masks for SV_TYPE_WORKSTATION 
        /// (0x00000001) and SV_TYPE_SERVER (0x00000002)
        /// </summary>
        public static extern int NetServerEnum(
            string ServerNane, // must be null
            int dwLevel,
            ref IntPtr pBuf,
            int dwPrefMaxLen,
            out int dwEntriesRead,
            out int dwTotalEntries,
            int dwServerType,
            string domain, // null for login domain
            out int dwResumeHandle
            );

        //declare the Netapi32 : NetApiBufferFree method import
        [DllImport("Netapi32", SetLastError = true),
        SuppressUnmanagedCodeSecurityAttribute]

        /// <summary>
        /// Netapi32.dll : The NetApiBufferFree function frees 
        /// the memory that the NetApiBufferAllocate function allocates. 
        /// Call NetApiBufferFree to free
        /// the memory that other network 
        /// management functions return.
        /// </summary>
        public static extern int NetApiBufferFree(
            IntPtr pBuf);

        //create a _SERVER_INFO_100 STRUCTURE
        [StructLayout(LayoutKind.Sequential)]
        public struct _SERVER_INFO_100
        {
            internal int sv100_platform_id;
            [MarshalAs(UnmanagedType.LPWStr)]
            internal string sv100_name;
        }
        #endregion
        #region Public Constructor
        /// <SUMMARY>
        /// Constructor, simply creates a new NetworkBrowser object
        /// </SUMMARY>
        public NetworkBrowser()
        {

        }
        #endregion
        #region Public Methods
        /// <summary>
        /// Uses the DllImport : NetServerEnum
        /// with all its required parameters
        /// (see http://msdn.microsoft.com/library/default.asp?
        ///      url=/library/en-us/netmgmt/netmgmt/netserverenum.asp
        /// for full details or method signature) to
        /// retrieve a list of domain SV_TYPE_WORKSTATION
        /// and SV_TYPE_SERVER PC's
        /// </summary>
        /// <returns>Arraylist that represents
        /// all the SV_TYPE_WORKSTATION and SV_TYPE_SERVER
        /// PC's in the Domain</returns>
        public ArrayList getNetworkComputers()
        {
            //local fields
            ArrayList networkComputers = new ArrayList();
            const int MAX_PREFERRED_LENGTH = -1;
            int SV_TYPE_WORKSTATION = 1;
            int SV_TYPE_SERVER = 2;
            IntPtr buffer = IntPtr.Zero;
            IntPtr tmpBuffer = IntPtr.Zero;
            int entriesRead = 0;
            int totalEntries = 0;
            int resHandle = 0;
            int sizeofINFO = Marshal.SizeOf(typeof(_SERVER_INFO_100));


            try
            {
                //call the DllImport : NetServerEnum 
                //with all its required parameters
                //see http://msdn.microsoft.com/library/
                //default.asp?url=/library/en-us/netmgmt/netmgmt/netserverenum.asp
                //for full details of method signature
                int ret = NetServerEnum(null, 100, ref buffer, 
                    MAX_PREFERRED_LENGTH,
                    out entriesRead,
                    out totalEntries, SV_TYPE_WORKSTATION | 
                    SV_TYPE_SERVER, null, out 
                    resHandle);
                //if the returned with a NERR_Success 
                //(C++ term), =0 for C#
                if (ret == 0)
                {
                    //loop through all SV_TYPE_WORKSTATION 
                    //and SV_TYPE_SERVER PC's
                    for (int i = 0; i < totalEntries; i++)
                    {
                        //get pointer to, Pointer to the 
                        //buffer that received the data from
                        //the call to NetServerEnum. 
                        //Must ensure to use correct size of 
                        //STRUCTURE to ensure correct 
                        //location in memory is pointed to
                        tmpBuffer = new IntPtr((int)buffer + 
                                   (i * sizeofINFO));
                        //Have now got a pointer to the list 
                        //of SV_TYPE_WORKSTATION and 
                        //SV_TYPE_SERVER PC's, which is unmanaged memory
                        //Needs to Marshal data from an 
                        //unmanaged block of memory to a 
                        //managed object, again using 
                        //STRUCTURE to ensure the correct data
                        //is marshalled 
                        _SERVER_INFO_100 svrInfo = (_SERVER_INFO_100)
                            Marshal.PtrToStructure(tmpBuffer, 
                                    typeof(_SERVER_INFO_100));

                        //add the PC names to the ArrayList
                        networkComputers.Add(svrInfo.sv100_name);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Problem with acessing " + 
                    "network computers in NetworkBrowser " +
                    "\r\n\r\n\r\n" + ex.Message,
                    "Error", MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
                return null;
            }
            finally
            {
                //The NetApiBufferFree function frees 
                //the memory that the 
                //NetApiBufferAllocate function allocates
                NetApiBufferFree(buffer);
            }
            //return entries found
            return networkComputers;

        }
        #endregion
    }
    #endregion
}

I have tried to comment the code as much as possible, so I'll just let the code do the talking. You've heard enough about me.

Points of Interest

On a personal level, I have found this to be quite a rewarding exercise, and I found that consuming DLLs within C# is quite a black art. But in the end, it's all worth it.

History

  • v1.0 - 21/10/06.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Sacha Barber
Software Developer (Senior)
United Kingdom United Kingdom
Member
I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)
 
- MSc (Passed with distinctions), in Information Technology for E-Commerce
- BSc Hons (1st class) in Computer Science & Artificial Intelligence
 
Both of these at Sussex University UK.
 
Award(s)

I am lucky enough to have won a few awards for Zany Crazy code articles over the years

  • Microsoft C# MVP 2013
  • Codeproject MVP 2013
  • Microsoft C# MVP 2012
  • Codeproject MVP 2012
  • Microsoft C# MVP 2011
  • Codeproject MVP 2011
  • Microsoft C# MVP 2010
  • Codeproject MVP 2010
  • Microsoft C# MVP 2009
  • Codeproject MVP 2009
  • Microsoft C# MVP 2008
  • Codeproject MVP 2008
  • And numerous codeproject awards which you can see over at my blog

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5memberbaldgeek23 Apr '13 - 9:49 
QuestionIs this supposed to work on Windows 8? [modified]memberuhaus27 Jan '13 - 5:43 
AnswerRe: Is this supposed to work on Windows 8?memberJason Henderson12 Mar '13 - 7:10 
GeneralMy vote of 5memberCoderMan200714 Oct '12 - 1:51 
QuestionGreat work! How to get share folders in local area network?memberxiaokang08825 May '12 - 3:00 
QuestionLicense?membercgordon_131 Mar '12 - 4:01 
AnswerRe: License?mvpSacha Barber1 Mar '12 - 5:56 
GeneralMy vote of 5memberVery_Suave26 Feb '12 - 0:19 
GeneralMy vote of 5memberMember 424252629 Dec '11 - 4:29 
QuestionFind server in domain. [modified]memberprajaktakarmarkar28 Dec '11 - 22:24 
AnswerRe: Find server in domain.mvpSacha Barber29 Dec '11 - 7:20 
GeneralRe: Find server in domain.memberprajaktakarmarkar29 Dec '11 - 17:59 
QuestionNot 100% reliablememberTaneth16 Nov '11 - 6:44 
Generalgetting list of all systems in teh NETWORKmembersvknair17 Apr '11 - 20:07 
GeneralRe: getting list of all systems in teh NETWORKmvpSacha Barber17 Apr '11 - 21:32 
GeneralRe: getting list of all systems in teh NETWORKmembersvknair20 Apr '11 - 19:25 
GeneralRe: getting list of all systems in teh NETWORKmvpSacha Barber20 Apr '11 - 19:52 
GeneralRe: getting list of all systems in teh NETWORKmvpSacha Barber20 Apr '11 - 19:56 
GeneralRe: getting list of all systems in teh NETWORKmembersvknair21 Apr '11 - 19:26 
GeneralIt doesn't seem to work as expectedmembersdancer7520 Feb '11 - 23:33 
GeneralRe: It doesn't seem to work as expectedmemberMichael Janulaitis28 Apr '11 - 16:58 
AnswerRe: It doesn't seem to work as expectedmemberMember 5015675 Dec '11 - 22:20 
GeneralWant IPAddress with namemembertahirmakhdoom20 Jan '11 - 0:18 
QuestionOnly able to view my own computermemberpaoloTheCool12 Sep '10 - 9:52 
GeneralSERVER_INFO_101memberPhil_w24 Aug '10 - 22:39 
GeneralRe: SERVER_INFO_101memberPhil_w25 Aug '10 - 3:22 
GeneralRe: SERVER_INFO_101mvpSacha Barber25 Aug '10 - 4:51 
QuestionHow to retrieve the owner of a network server?memberMember 271871112 Aug '10 - 9:43 
AnswerRe: How to retrieve the owner of a network server?mvpSacha Barber12 Aug '10 - 19:51 
GeneralGetting an error 71 which is not listed anywheremembers1s110 Mar '10 - 5:30 
GeneralRe: Getting an error 71 which is not listed anywheremvpSacha Barber10 Mar '10 - 6:30 
QuestionDont have In managed code still? Dou yo now other app?memberjuliotrujilloleon12 Jan '10 - 5:47 
AnswerRe: Dont have In managed code still? Dou yo now other app?mvpSacha Barber12 Jan '10 - 5:57 
GeneralERROR_NO_BROWSER_SERVERS_FOUND 6118memberSnakefoot5 Nov '09 - 1:47 
GeneralRe: ERROR_NO_BROWSER_SERVERS_FOUND 6118memberSnakefoot5 Nov '09 - 3:26 
GeneralRe: ERROR_NO_BROWSER_SERVERS_FOUND 6118memberSnakefoot13 Dec '09 - 23:35 
GeneralExcellent code, was looking for it since months [modified]memberAjay Kewale8 Oct '09 - 4:46 
GeneralExcellent!!memberedazccode1 Aug '09 - 6:02 
GeneralRe: Excellent!!mvpSacha Barber1 Aug '09 - 20:43 
GeneralNice Article, Want to know 1 thingmemberKooki10 Jun '09 - 1:33 
GeneralRe: Nice Article, Want to know 1 thingmvpSacha Barber1 Aug '09 - 20:45 
GeneralThanks for the great work... and... api documentationmemberbarny6 Apr '09 - 8:59 
GeneralRe: Thanks for the great work... and... api documentationmemberpranav9520 May '10 - 17:21 
Generalget all shared forders in network computersmember_Armen29 Mar '09 - 11:36 
GeneralRe: get all shared forders in network computersmvpSacha Barber29 Mar '09 - 21:25 
GeneralGetting a Computers WorkGroup Namemembers4souhail21 Mar '09 - 20:05 
GeneralRe: Getting a Computers WorkGroup NamemvpSacha Barber21 Mar '09 - 21:39 
NewsDoesn't always return machines in the workgroupmemberTennChris9 Jan '09 - 4:54 
QuestionHow can I get domain listmemberforeverlove16 Nov '08 - 21:53 
QuestionHow can we get Machine name in domainmemberforeverlove5 Nov '08 - 5:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 26 Oct 2006
Article Copyright 2006 by Sacha Barber
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid