tags:

views:

273

answers:

3

I have a list of the name of shared computers of the form "\\computer" and need to find shared folders on those machines.

All of the .Net methods I've been able to find require a valid UNC to be called but since I only have the list of computers I cannot make a valid UNC.

Is there a way to discover all of the shared folders on a computer using only the computer's name (like "\\computer")?

+4  A: 

There is no way to do this in the standard BCL. You'll need to access the native function NetShareEnum for this purpose.

This is a bit of work though. Luckily someone on CodeProject already did it and outputted a library wrapping it into a nice managed API.

JaredPar
My intuition says there's a WMI method somewhere, though that's not to say it's necessarily better than the Win API one.
Noldorin
A: 

CodeProject has an article that includes a wrapper for the WMI classes:

WMI wrapper

The wrapper is written in VB.NET but of course it can be built into a DLL and called from C#.

[So Noldorin, you're right.]

Jay Riggs
+3  A: 

Try this Code,

Tested in Windows XP, Windows Vista.

using System;
using System.Runtime.InteropServices;

namespace ConsoleApplication
{

  class Program
  {

        public enum RESOURCE_SCOPE_NET
        {
        RESOURCE_CONNECTED  = 0x00000001,
        RESOURCE_GLOBALNET  = 0x00000002,
        RESOURCE_REMEMBERED = 0x00000003,
        RESOURCE_RECENT     = 0x00000004,
        RESOURCE_CONTEXT    = 0x00000005
        }

        public enum RESOURCE_TYPE_NET
        {
        RESOURCETYPE_ANY      = 0x00000000,
        RESOURCETYPE_DISK     = 0x00000001,
        RESOURCETYPE_PRINT    = 0x00000002,
        RESOURCETYPE_RESERVED = 0x00000008,
        }

        public enum RESOURCE_USAGE_NET
        {
        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 RESOURCE_DISPLAYTYPE_NET
        {
          RESOURCEDISPLAYTYPE_GENERIC = 0x00000000,
          RESOURCEDISPLAYTYPE_DOMAIN  = 0x00000001,
          RESOURCEDISPLAYTYPE_SERVER  = 0x00000002,
          RESOURCEDISPLAYTYPE_SHARE   = 0x00000003,
          RESOURCEDISPLAYTYPE_FILE    = 0x00000004,
          RESOURCEDISPLAYTYPE_GROUP   = 0x00000005,
          RESOURCEDISPLAYTYPE_NETWORK = 0x00000006,
          RESOURCEDISPLAYTYPE_ROOT    = 0x00000007,
          RESOURCEDISPLAYTYPE_SHAREADMIN   = 0x00000008,
          RESOURCEDISPLAYTYPE_DIRECTORY    = 0x00000009,
          RESOURCEDISPLAYTYPE_TREE         = 0x0000000A,
          RESOURCEDISPLAYTYPE_NDSCONTAINER = 0x0000000B
        }     

        [DllImport("mpr.dll", CharSet=CharSet.Auto)]
        public static extern int WNetEnumResource(
        IntPtr   hEnum,
        ref int  lpcCount,
        IntPtr   lpBuffer,
        ref int  lpBufferSize );

        [DllImport("mpr.dll", CharSet=CharSet.Auto)]
        public static extern int WNetOpenEnum( RESOURCE_SCOPE_NET dwScope, RESOURCE_TYPE_NET dwType,  RESOURCE_USAGE_NET dwUsage,  [MarshalAs(UnmanagedType.AsAny)][In] Object lpNetResource,  out IntPtr lphEnum);
        [DllImport("mpr.dll", CharSet=CharSet.Auto)]
        public static extern int WNetCloseEnum( IntPtr hEnum );



        public struct NETRESOURCE
        {
          public RESOURCE_SCOPE_NET dwScope;
          public RESOURCE_TYPE_NET dwType;
          public RESOURCE_DISPLAYTYPE_NET dwDisplayType;
          public RESOURCE_USAGE_NET dwUsage;
          [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPTStr)]
          public string lpLocalName;
          [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPTStr)]
          public string lpRemoteName;
          [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPTStr)]
          public string lpComment;
          [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPTStr)]
          public string lpProvider;

        }


        private static void InitScan(Object Dummy)

        {
        int iRet;
        IntPtr ptrHandle = new IntPtr();
        try

        {
          iRet = WNetOpenEnum(RESOURCE_SCOPE_NET.RESOURCE_GLOBALNET, RESOURCE_TYPE_NET.RESOURCETYPE_ANY, RESOURCE_USAGE_NET.RESOURCEUSAGE_ALL, Dummy, out ptrHandle);

        if( iRet != 0 )
        {
        return;
        }

        int entries;
        int buffer = 16384;
        IntPtr ptrBuffer = Marshal.AllocHGlobal( buffer );
        NETRESOURCE nr;

        for(;;)
        {
        entries = -1;
        buffer = 16384;
        iRet =WNetEnumResource( ptrHandle, ref entries, ptrBuffer, ref buffer );

        if( (iRet != 0) || (entries < 1) )
        {
        break;
        }

        Int32 ptr = ptrBuffer.ToInt32();
        for( int i = 0; i < entries; i++ )
        {
        nr = (NETRESOURCE)Marshal.PtrToStructure( new IntPtr(ptr), typeof(NETRESOURCE) );
        if(RESOURCE_USAGE_NET.RESOURCEUSAGE_CONTAINER == (nr.dwUsage & RESOURCE_USAGE_NET.RESOURCEUSAGE_CONTAINER))

        {
          InitScan(nr);
        }

        ptr += Marshal.SizeOf( nr );
        Console.WriteLine(" {0} : LocalName='{1}' RemoteName='{2}' Description='{3}' Provider='{4}'", nr.dwDisplayType.ToString(), nr.lpLocalName, nr.lpRemoteName,nr.lpComment,nr.lpProvider );
        }

        }

        Marshal.FreeHGlobal( ptrBuffer );
        iRet =WNetCloseEnum( ptrHandle );
        }

        catch(Exception e)

        {
          Console.WriteLine("Error ** "+e.Message+" ** Trace "+e.StackTrace);
        }

        }


    static void Main(string[] args)
    {
      Console.WriteLine("Scannig Network....Wait a moment , be patient please ;)");
      InitScan(null);
      Console.WriteLine("Scan Network Finished");
      Console.Read();
    }
  }
}

Bye.

RRUZ
Thanks for the code, it definitely works and allows you to tweak things a bit more but the API above is just way too nice. This could be a better solution if you're familiar with C# structs.
Mark Striemer