获取共享计算机上目录列表 .NET

4

我有一个共享计算机名称列表,格式为“\\计算机”,需要查找这些计算机上的共享文件夹。

我能找到的所有.Net方法都需要调用有效的UNC,但由于我只有计算机列表,因此无法生成有效的UNC。

是否有一种方法可以仅使用计算机名称(如“\\计算机”)来发现计算机上的所有共享文件夹?

3个回答

5

尝试这段代码,

在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();
    }
  }
}

再见。


感谢提供代码,它肯定有效,并且允许您进行更多微调,但上面的API太棒了。如果您熟悉C#结构体,则这可能是更好的解决方案。 - Mark Striemer
由于某些原因,它无法在 Windows 服务中正常工作。 - Gichamba

4

2
我的直觉告诉我在某个地方有一个 WMI 方法,不过这并不意味着它一定比 Win API 更好。 - Noldorin

0

CodeProject有一篇文章,其中包括WMI类的包装器:

WMI wrapper

这个包装器是用VB.NET编写的,但当然它可以被构建成一个DLL并从C#中调用。

[所以Noldorin,你是正确的。]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接