网络文件夹浏览器服务

在网上有一些类似的问题 – 甚至在这里有一些问题,但即使这些问题似乎很高兴,我找不到真正做到我需要的东西。

我正在尝试将远程目录浏览function添加到基于Web的管理控制面板(基于Intranet)。

此时我不需要担心安全性,因为这是在其他地方处理的。

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

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

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

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

干杯

您可以使用Interop使用此处描述的方法。

我对代码做了一些修改以得出这个。 我没有对此进行过广泛的测试,所以它可能有错误,但它应该让你开始。

private List GetSubDirectories(string serverName, string folderPath) { List subDirectories = new List(); 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]\*"); 

您必须按照MSDN添加“\ *”

在网络共享上,您可以使用以下forms的lpFileName:“\ Server \ Share *”。 但是,您不能使用指向共享本身的lpFileName; 例如,“\ Server \ Share”无效。

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

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

好吧,实际上它可以使用NetShareEnum Win32APIfunction完成 。

但这里是.NET包装类,用于枚举本地和远程计算机上的网络共享,并将本地文件路径转换为UNC路径。 请参阅文章网络共享和UNC路径 。

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

要枚举某些计算机的共享,如果隐藏的管理共享(如C$ADMIN$print$等)对您不重要或使用NetShareEnum枚举所有共享,则可以使用WNetEnumResource本机函数。

相应的代码可以是

 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 GetShares(string computerName) { var resources = new List(); 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 GetAllShares (string computerName) { var shares = new List (); 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 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。 它不包含真正的错误报告。