【问题标题】:Get a list of directories on a shared computer .NET获取共享计算机 .NET 上的目录列表
【发布时间】:2009-09-16 23:02:18
【问题描述】:

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

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

有没有办法仅使用计算机名称(如“\\computer”)发现计算机上的所有共享文件夹?

【问题讨论】:

    标签: c# .net networking


    【解决方案1】:

    试试这个代码,

    在 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# 结构,这可能是一个更好的解决方案。
    • 由于某种原因,它在 Windows 服务中不起作用
    【解决方案2】:

    在标准 BCL 中无法做到这一点。为此,您需要访问本机函数 NetShareEnum。

    不过,这有点工作。幸运的是,CodeProject 上的某个人已经这样做了,并输出了一个库,将其包装成一个很好的托管 API。

    【讨论】:

    • 我的直觉说在某处有一个 WMI 方法,但这并不是说它一定比 Win API 更好。
    【解决方案3】:

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

    WMI wrapper

    包装器是用 VB.NET 编写的,但当然可以将其构建到 DLL 中并从 C# 中调用。

    [所以诺多林,你是对的。]

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-10-28
      • 2021-08-31
      • 2010-09-28
      • 1970-01-01
      • 2015-08-28
      • 1970-01-01
      • 2012-02-18
      相关资源
      最近更新 更多