Click here to Skip to main content
15,891,828 members
Articles / Programming Languages / C#

Enumerating Network Resources

Rate me:
Please Sign up or sign in to vote.
4.80/5 (35 votes)
27 Feb 2004CPOL10 min read 208.2K   8.3K   59  
Using the WNetEnumResource API from C#
using System;
using System.Collections;
using System.Runtime.InteropServices;

namespace ServerEnumerator
{
    /// <summary>
    /// The ServerEnum class is used to enumerate servers on the
    /// network.
    /// </summary>
    ///
	public enum ResourceScope
	{
		RESOURCE_CONNECTED = 1,
		RESOURCE_GLOBALNET,
		RESOURCE_REMEMBERED,
		RESOURCE_RECENT,
		RESOURCE_CONTEXT
	};

	public enum ResourceType
	{
		RESOURCETYPE_ANY,
		RESOURCETYPE_DISK,
		RESOURCETYPE_PRINT,
		RESOURCETYPE_RESERVED
	};

	public enum ResourceUsage
	{
		RESOURCEUSAGE_CONNECTABLE   = 0x00000001,
		RESOURCEUSAGE_CONTAINER     = 0x00000002,
		RESOURCEUSAGE_NOLOCALDEVICE = 0x00000004,
		RESOURCEUSAGE_SIBLING       = 0x00000008,
		RESOURCEUSAGE_ATTACHED      = 0x00000010,
		RESOURCEUSAGE_ALL           = (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED),
	};
	
	public enum ResourceDisplayType
	{
		RESOURCEDISPLAYTYPE_GENERIC,
		RESOURCEDISPLAYTYPE_DOMAIN,
		RESOURCEDISPLAYTYPE_SERVER,
		RESOURCEDISPLAYTYPE_SHARE,
		RESOURCEDISPLAYTYPE_FILE,
		RESOURCEDISPLAYTYPE_GROUP,
		RESOURCEDISPLAYTYPE_NETWORK,
		RESOURCEDISPLAYTYPE_ROOT,
		RESOURCEDISPLAYTYPE_SHAREADMIN,
		RESOURCEDISPLAYTYPE_DIRECTORY,
		RESOURCEDISPLAYTYPE_TREE,
		RESOURCEDISPLAYTYPE_NDSCONTAINER
	};

    public class ServerEnum : IEnumerable
    {
        enum ErrorCodes
        {
            NO_ERROR = 0,
            ERROR_NO_MORE_ITEMS = 259
        };

        [StructLayout(LayoutKind.Sequential)]
        private class NETRESOURCE 
        {
            public ResourceScope       dwScope = 0;
            public ResourceType        dwType = 0;
            public ResourceDisplayType dwDisplayType = 0;
            public ResourceUsage       dwUsage = 0;
            public string              lpLocalName = null;
            public string              lpRemoteName = null;
            public string              lpComment = null;
            public string              lpProvider = null;
        };

        private ArrayList aData = new ArrayList();

        public int Count
        {
            get { return aData.Count; }
        }

        [DllImport("Mpr.dll", EntryPoint="WNetOpenEnumA", CallingConvention=CallingConvention.Winapi)]
        private static extern ErrorCodes WNetOpenEnum(ResourceScope dwScope, ResourceType dwType, ResourceUsage dwUsage, NETRESOURCE p, out IntPtr lphEnum);

        [DllImport("Mpr.dll", EntryPoint="WNetCloseEnum", CallingConvention=CallingConvention.Winapi)]
        private static extern ErrorCodes WNetCloseEnum(IntPtr hEnum);

        [DllImport("Mpr.dll", EntryPoint="WNetEnumResourceA", CallingConvention=CallingConvention.Winapi)]
        private static extern ErrorCodes WNetEnumResource(IntPtr hEnum, ref uint lpcCount, IntPtr buffer, ref uint lpBufferSize);

		private	void EnumerateServers(NETRESOURCE pRsrc, ResourceScope scope, ResourceType type, ResourceUsage usage, ResourceDisplayType displayType)
		{
			uint		bufferSize = 16384;
			IntPtr		buffer	= Marshal.AllocHGlobal((int) bufferSize);
			IntPtr		handle = IntPtr.Zero;
			ErrorCodes	result;
			uint		cEntries = 1;

			result = WNetOpenEnum(scope, type, usage, pRsrc, out handle);

			if (result == ErrorCodes.NO_ERROR)
			{
				do
				{
					result = WNetEnumResource(handle, ref cEntries,	buffer,	ref	bufferSize);

					if (result == ErrorCodes.NO_ERROR)
					{
						Marshal.PtrToStructure(buffer, pRsrc);

						if (pRsrc.dwDisplayType	== displayType)
							aData.Add(pRsrc.lpRemoteName);

						if ((pRsrc.dwUsage & ResourceUsage.RESOURCEUSAGE_CONTAINER)	== ResourceUsage.RESOURCEUSAGE_CONTAINER)
							EnumerateServers(pRsrc,	scope, type, usage,	displayType);
					}
					else if	(result	!= ErrorCodes.ERROR_NO_MORE_ITEMS)
						break;
				} while	(result	!= ErrorCodes.ERROR_NO_MORE_ITEMS);

				WNetCloseEnum(handle);
			}

			Marshal.FreeHGlobal((IntPtr) buffer);
		}

		public ServerEnum(ResourceScope scope, ResourceType type, ResourceUsage usage, ResourceDisplayType displayType)
		{
			NETRESOURCE pRsrc = new NETRESOURCE();

			EnumerateServers(pRsrc, scope, type, usage, displayType);
		}
		#region IEnumerable Members

		public IEnumerator GetEnumerator()
		{
			return aData.GetEnumerator();
		}

		#endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
I've been programming for 35 years - started in machine language on the National Semiconductor SC/MP chip, moved via the 8080 to the Z80 - graduated through HP Rocky Mountain Basic and HPL - then to C and C++ and now C#.

I used (30 or so years ago when I worked for Hewlett Packard) to repair HP Oscilloscopes and Spectrum Analysers - for a while there I was the one repairing DC to daylight SpecAns in the Asia Pacific area.

Afterward I was the fourth team member added to the Australia Post EPOS project at Unisys Australia. We grew to become an A$400 million project. I wrote a few device drivers for the project under Microsoft OS/2 v 1.3 - did hardware qualification and was part of the rollout team dealing directly with the customer.

Born and bred in Melbourne Australia, now living in Scottsdale Arizona USA, became a US Citizen on September 29th, 2006.

I work for a medical insurance broker, learning how to create ASP.NET websites in VB.Net and C#. It's all good.

Oh, I'm also a Kentucky Colonel. http://www.kycolonels.org

Comments and Discussions