2012-03-21 162 views
1

网上有一些类似的问题 - 甚至在这里有一些,但即使提问者似乎很高兴,我找不到实际上做我需要的东西。网络文件夹浏览器服务

我试图将远程目录浏览功能添加到基于Web的管理控制面板(基于Intranet)。

我现在不需要担心安全问题,因为这是在其他地方处理的。

为此,我使用一个接受服务器名称和共享/文件夹路径作为参数的web服务。我只需要它返回这个路径的子目录,如果有的话。

听起来不那么难,是吗?那么,这是(至少对我来说)

我需要帮助的唯一一点是实际上产生的服务器和路径提供的目录列表。

所有帮助表示赞赏,但请不要只链接到一个网站,因为我可能已经看到它,但未能得到一个工作解决方案;其中大部分甚至似乎没有试图去做标题所暗示的。 一些解释也会有帮助!

干杯

+0

“网络文件夹”是什么意思? SMB分享? NFS? FTP? WebDAV的?列出文件夹对于每个协议都是完全不同的... – 2012-03-21 17:01:46

+0

这些是标准的Windows Server共享文件夹及其子文件夹。 – CompanyDroneFromSector7G 2012-03-21 17:04:46

回答

0

您可以使用方法here using Interop

我对代码做了一些修改来提出这个问题。 我还没有广泛测试过,所以它可能有错误,但它应该让你开始。

private List<string> GetSubDirectories(string serverName, string folderPath) 
{ 
     List<string> subDirectories = new List<string>(); 
     string folder_path = Path.Combine(serverName, folderPath);    
     IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); 

     WIN32_FIND_DATA findData; 

     IntPtr findHandle; 

     findHandle = FindFirstFile(folder_path, out findData); 
     if (findHandle == INVALID_HANDLE_VALUE) 
     { 
      int error = Marshal.GetLastWin32Error(); 
      Console.WriteLine(error.ToString()); 
      return null; 
     } 

     do 
     { 
      try 
      { 
       if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) 
        subDirectories.Add(findData.cFileName);      
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.ToString()); 
      } 
     } 
     while (FindNextFile(findHandle, out findData)); 
     FindClose(findHandle); 

     return subDirectories; 
    } 

    public const int FILE_ATTRIBUTE_DIRECTORY = 0x10; 

    [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Auto)] 
    public static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData); 

    [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Auto)] 
    public static extern bool FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData); 

    [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Auto)] 
    public static extern bool FindClose(IntPtr hFindFile); 

    [StructLayout(LayoutKind.Sequential)] 
    public struct FILETIME 
    { 
     public uint dwLowDateTime; 
     public uint dwHighDateTime; 
    }; 

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
    public struct WIN32_FIND_DATA 
    { 
     public uint dwFileAttributes; 
     public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime; 
     public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime; 
     public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime; 
     public uint nFileSizeHigh; 
     public uint nFileSizeLow; 
     public uint dwReserved0; 
     public uint dwReserved1; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] 
     public string cFileName; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] 
     public string cAlternateFileName; 
    } 


    [DllImport("kernel32.dll", CharSet = CharSet.Auto)] 
    public static extern bool CloseHandle(IntPtr handle); 

} 

你可以把它想:

var subdirectories = GetSubDirectories(@"\\[serverName]", @"[folderPath]\*"); 

您必须添加 “\ *” as per MSDN

在网络共享,您可以在的形式使用lpFileName的对象 以下内容:“\ Server \ Share *”。但是,您不能使用指向共享本身的lpFileName ;例如,“\ Server \ Share”不是 有效。

+0

谢谢 - 只要我有共享名称,这似乎工作。有没有办法列出这些股票,或者这是完全不同的东西? – CompanyDroneFromSector7G 2012-03-23 10:47:28

+0

要枚举共享,您需要一种方法,如[此处所述](http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/19b88200-3dfd-4042-b16a-1f514dd5e1f9/)。 – 2012-03-23 23:55:20

+0

这是最适合我的解决方案。感谢所有的建议。 – CompanyDroneFromSector7G 2012-03-28 11:45:39

0

不知道我们是否可以做到这一点。我们有类似的问题,但最终通过提供共享路径(\ SERVERNAME \ FOLDER)来解决它。

最重要的web服务应该使用具有完全权限访问该目录的帐户否则与权限相关的异常将被抛出到调用客户端。

0

呃,实际上它可以使用NetShareEnum Win32API function来完成。

但是,这里是.NET包装类来枚举本地和远程机器上的网络共享,并将本地文件路径转换为UNC路径。请参阅文章Network Shares and UNC paths

+0

我看过那篇文章,但它没有做我所需要的。我不想枚举本地计算机上的共享,我想知道远程计算机上的共享 - 这就是为什么服务器名称是必需的。 – CompanyDroneFromSector7G 2012-03-26 15:50:21

+0

你见过'ShareCollection'类的'GetShares'静态方法吗? – 2012-03-27 06:14:53

+0

我现在有! :$谢谢 - 我正在查看不同的选项。 – CompanyDroneFromSector7G 2012-03-28 09:40:20

0

要在.NET中枚举指定文件夹的子文件夹,可以使用例如DirectoryInfo.EnumerateDirectories方法。

要列举一些计算机可以使用WNetEnumResource本地函数,如果隐藏管理共享像C$ADMIN$print$等等都没有对你很重要,或者使用NetShareEnum枚举所有股份的股份。

相应的代码可以是

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.IO; 
using System.Runtime.InteropServices; 

namespace Subfolders { 
    static internal class Native { 
     [DllImport ("Netapi32.dll", SetLastError = true)] 
     internal static extern uint NetApiBufferFree (IntPtr buffer); 

     [DllImport ("Netapi32.dll", CharSet = CharSet.Unicode)] 
     internal static extern uint NetShareEnum (
      string serverName, 
      int level, 
      ref IntPtr bufPtr, 
      uint prefmaxlen, 
      ref int entriesread, 
      ref int totalentries, 
      ref int resumeHandle 
     ); 

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

     [DllImport ("MPR.dll", CharSet = CharSet.Auto)] 
     internal static extern uint WNetOpenEnum(ResourceScope dwScope, ResourceType dwType, ResourceUsage dwUsage, 
      IntPtr lpNetResource, out IntPtr lphEnum); 

     [DllImport ("MPR.dll", CharSet = CharSet.Auto)] 
     internal static extern uint WNetCloseEnum(IntPtr hEnum); 

     internal const uint MaxPreferredLength = 0xFFFFFFFF; 
     internal const int NerrSuccess = 0; 
     internal enum NetError : uint { 
      NerrSuccess = 0, 
      NerrBase = 2100, 
      NerrUnknownDevDir = (NerrBase + 16), 
      NerrDuplicateShare = (NerrBase + 18), 
      NerrBufTooSmall = (NerrBase + 23), 
     } 
     internal enum ShareType : uint { 
      StypeDisktree = 0, 
      StypePrintq = 1, 
      StypeDevice = 2, 
      StypeIpc = 3, 
      StypeSpecial = 0x80000000, 
     } 
     [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
     public struct ShareInfo1 { 
      public string shi1_netname; 
      public uint shi1_type; 
      public string shi1_remark; 
      public ShareInfo1 (string sharename, uint sharetype, string remark) { 
       shi1_netname = sharename; 
       shi1_type = sharetype; 
       shi1_remark = remark; 
      } 
      public override string ToString() { 
       return shi1_netname; 
      } 
     } 
     public enum ResourceScope: uint { 
      ResourceConnected = 0x00000001, 
      ResourceGlobalnet = 0x00000002, 
      ResourceRemembered = 0x00000003, 
      ResourceRecent = 0x00000004, 
      ResourceContext = 0x00000005 
     } 
     public enum ResourceType: uint { 
      ResourcetypeAny = 0x00000000, 
      ResourcetypeDisk = 0x00000001, 
      ResourcetypePrint = 0x00000002, 
      ResourcetypeReserved = 0x00000008, 
      ResourcetypeUnknown = 0xFFFFFFFF 
     } 
     public enum ResourceUsage: uint { 
      ResourceusageConnectable = 0x00000001, 
      ResourceusageContainer = 0x00000002, 
      ResourceusageNolocaldevice = 0x00000004, 
      ResourceusageSibling = 0x00000008, 
      ResourceusageAttached = 0x00000010, 
      ResourceusageAll = (ResourceusageConnectable | ResourceusageContainer | ResourceusageAttached), 
      ResourceusageReserved = 0x80000000 
     } 
     public enum ResourceDisplaytype: uint { 
      ResourcedisplaytypeGeneric = 0x00000000, 
      ResourcedisplaytypeDomain = 0x00000001, 
      ResourcedisplaytypeServer = 0x00000002, 
      ResourcedisplaytypeShare = 0x00000003, 
      ResourcedisplaytypeFile = 0x00000004, 
      ResourcedisplaytypeGroup = 0x00000005, 
      ResourcedisplaytypeNetwork = 0x00000006, 
      ResourcedisplaytypeRoot = 0x00000007, 
      ResourcedisplaytypeShareadmin = 0x00000008, 
      ResourcedisplaytypeDirectory = 0x00000009, 
      ResourcedisplaytypeTree = 0x0000000A, 
      ResourcedisplaytypeNdscontainer = 0x0000000B 
     } 
     [StructLayout (LayoutKind.Sequential)] 
     public struct NetResource { 
      public ResourceScope dwScope; 
      public ResourceType dwType; 
      public ResourceDisplaytype dwDisplayType; 
      public ResourceUsage dwUsage; 
      [MarshalAs (UnmanagedType.LPTStr)] 
      public string lpLocalName; 
      [MarshalAs (UnmanagedType.LPTStr)] 
      public string lpRemoteName; 
      [MarshalAs (UnmanagedType.LPTStr)] 
      public string lpComment; 
      [MarshalAs (UnmanagedType.LPTStr)] 
      public string lpProvider; 
     } 
    } 
    class Program { 
     static IEnumerable<string> GetShares(string computerName) { 
      var resources = new List<string>(); 
      IntPtr hEnum = IntPtr.Zero, pResource = IntPtr.Zero; 
      try { 
       var resource = new Native.NetResource(); 
       int bufferSize = 163840; 
       resource.dwType = Native.ResourceType.ResourcetypeAny; 
       resource.dwScope = Native.ResourceScope.ResourceGlobalnet; 
       resource.dwUsage = Native.ResourceUsage.ResourceusageContainer; 
       resource.lpRemoteName = computerName; 
       pResource = Marshal.AllocHGlobal(Marshal.SizeOf(resource)); 
       Marshal.StructureToPtr (resource, pResource, false); 
       uint status = Native.WNetOpenEnum (Native.ResourceScope.ResourceGlobalnet, 
                Native.ResourceType.ResourcetypeDisk, 
                0, 
                pResource, 
                out hEnum); 
       if (status != 0) 
        return resources; 

       int numberOfEntries = -1; 
       IntPtr pBuffer = Marshal.AllocHGlobal(bufferSize); 
       status = Native.WNetEnumResource (hEnum, ref numberOfEntries, pBuffer, ref bufferSize); 
       if (status == Native.NerrSuccess && numberOfEntries > 0) { 
        var ptr = pBuffer; 
        for (int i = 0; i < numberOfEntries; i++, ptr += Marshal.SizeOf(resource)) { 
         resource = (Native.NetResource)Marshal.PtrToStructure (ptr, typeof (Native.NetResource)); 
         resources.Add (resource.lpRemoteName.StartsWith (computerName + '\\', 
                     StringComparison.OrdinalIgnoreCase) 
              ? resource.lpRemoteName.Substring (computerName.Length + 1) 
              : resource.lpRemoteName); 
        } 
       } 
      } finally { 
       if (hEnum != IntPtr.Zero) { 
        Native.WNetCloseEnum (hEnum); 
       } 
       if (pResource != IntPtr.Zero) { 
        Marshal.FreeHGlobal(pResource); 
       } 
      } 
      return resources; 
     } 

     static IEnumerable<string> GetAllShares (string computerName) { 
      var shares = new List<string>(); 
      IntPtr bufPtr = IntPtr.Zero; 
      int entriesread = 0; 
      int totalentries = 0; 
      int resumeHandle = 0; 
      int nStructSize = Marshal.SizeOf (typeof (Native.ShareInfo1)); 
      try { 
       uint ret = Native.NetShareEnum (computerName, 1, ref bufPtr, 
        Native.MaxPreferredLength, 
        ref entriesread, 
        ref totalentries, 
        ref resumeHandle); 
       if (ret == (uint)Native.NetError.NerrSuccess) { 
        var currentPtr = bufPtr; 
        for (int i = 0; i < entriesread; i++) { 
         var shi1 = (Native.ShareInfo1)Marshal.PtrToStructure (currentPtr, typeof (Native.ShareInfo1)); 
         if ((shi1.shi1_type & ~(uint)Native.ShareType.StypeSpecial) == (uint)Native.ShareType.StypeDisktree) { 
          shares.Add (shi1.shi1_netname); 
         } 
         currentPtr = new IntPtr (currentPtr.ToInt32() + nStructSize); 
        } 
       } 
      } finally { 
       if (bufPtr != IntPtr.Zero) 
        Native.NetApiBufferFree (bufPtr); 
      } 
      return shares; 
     } 
     static IEnumerable<string> GetSubdirectories (string root) { 
      var dirInfo = new DirectoryInfo (root); 
      return (from info in dirInfo.EnumerateDirectories() select info.Name).ToList(); 
     } 
     static void Main() { 
      var root = @"\\OK01\Users"; 
      Console.WriteLine ("Subdirectories of {0}:", root); 
      foreach (var dir in GetSubdirectories (root)) { 
       Console.WriteLine (dir); 
      } 

      Console.WriteLine(); 
      root = @"\\OK01\Users\Public"; 
      Console.WriteLine ("Subdirectories of {0}:", root); 
      foreach (var dir in GetSubdirectories (root)) { 
       Console.WriteLine (dir); 
      } 

      Console.WriteLine(); 
      root = @"\\OK01"; 
      Console.WriteLine ("All Shares of {0} (inclusive hidden):", root); 
      foreach (var shareName in GetAllShares (root)) { 
       Console.WriteLine (shareName); 
      } 

      Console.WriteLine(); 
      root = @"\\OK01"; 
      Console.WriteLine ("Shares of {0}:", root); 
      foreach (var shareName in GetShares (root)) { 
       Console.WriteLine (shareName); 
      } 
     } 
    } 
} 

其产生像

Subdirectories of \\OK01\Users: 
All Users 
ASP.NET v4.0 
Default 
Default User 
MSSQL$SQL2012 
Oleg 
Public 

Subdirectories of \\OK01\Users\Public: 
Desktop 
Documents 
Downloads 
Favorites 
Libraries 
Music 
Pictures 
Recorded TV 
Roaming 
Videos 

All Shares of \\OK01 (inclusive hidden): 
ADMIN$ 
C$ 
print$ 
Q$ 
Users 
Virtual Machines 
VMware 

Shares of \\OK01: 
Users 
Virtual Machines 
VMware 

上面的代码被简化输出证明仅如何使用相应的API。它不包含真正的错误报告。