在各种业务需求中,我们经常要访问一个在网络中的目录,读取其中的文件或者是在其目录中创建文件,在.Net中我们主要使用mpr.dll中的WNetAddConnection2和WNetCancelConnection2来实现,下面是代码引入。
[DllImport("mpr.dll")] private static extern int WNetAddConnection2(NetResource netResource, string password, string username, int flags); [DllImport("mpr.dll")] private static extern int WNetCancelConnection2(string name, int flags, bool force);
在上述代码中使用到的NetResource 我们可以定义如下:
var netResource = new NetResource { Scope = ResourceScope.GlobalNetwork, ResourceType = ResourceType.Disk, DisplayType = ResourceDisplayType.Share, RemoteName = networkName };
参数RemoteName就是远程网络路径。比如@"\\10.5.5.5\Public\Test"。
using System; using System.ComponentModel; using System.Runtime.InteropServices; using System.Net; namespace Phoenix.Modules.Common.Service.Uploads { public class ConnectToSharedFolder : IDisposable { readonly string _networkName; public ConnectToSharedFolder(string networkName, NetworkCredential credentials) { _networkName = networkName; var netResource = new NetResource { Scope = ResourceScope.GlobalNetwork, ResourceType = ResourceType.Disk, DisplayType = ResourceDisplayType.Share, RemoteName = networkName }; var userName = string.IsNullOrEmpty(credentials.Domain) ? credentials.UserName : $@"{credentials.Domain}\{credentials.UserName}"; var result = WNetAddConnection2( netResource, credentials.Password, userName, 0); if (result != 0) { throw new Win32Exception(result, "Error connecting to remote share"); } } ~ConnectToSharedFolder() { Dispose(false); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { WNetCancelConnection2(_networkName, 0, true); } [DllImport("mpr.dll")] private static extern int WNetAddConnection2(NetResource netResource, string password, string username, int flags); [DllImport("mpr.dll")] private static extern int WNetCancelConnection2(string name, int flags, bool force); [StructLayout(LayoutKind.Sequential)] public class NetResource { public ResourceScope Scope; public ResourceType ResourceType; public ResourceDisplayType DisplayType; public int Usage; public string LocalName; public string RemoteName; public string Comment; public string Provider; } public enum ResourceScope : int { Connected = 1, GlobalNetwork, Remembered, Recent, Context }; public enum ResourceType : int { Any = 0, Disk = 1, Print = 2, Reserved = 8, } public enum ResourceDisplayType : int { Generic = 0x0, Domain = 0x01, Server = 0x02, Share = 0x03, File = 0x04, Group = 0x05, Network = 0x06, Root = 0x07, Shareadmin = 0x08, Directory = 0x09, Tree = 0x0a, Ndscontainer = 0x0b } } }
引入ConnectToSharedFolder、NetResource、ResourceScope,就可以直接添加代码写入文件了。
using Phoenix.Modules.Common.Service.Uploads; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Text; using System.Threading.Tasks; namespace ConsoleApp4_networkDic { class Program { public static string networkPath = @"\\10.5.5.5\test"; static NetworkCredential credentials = new NetworkCredential(@"test", "May"); public static string myNetworkPath = string.Empty; static void Main(string[] args) { string filename = "test.txt"; FileUpload(filename); Console.ReadKey(); } public static void FileUpload(string UploadURL) { try { using (new ConnectToSharedFolder(networkPath, credentials)) { var fileList = Directory.GetDirectories(networkPath); foreach (var item in fileList) { if (item.Contains("{ClientDocument}")) { myNetworkPath = item; } } myNetworkPath = networkPath+@"\" + UploadURL; using (FileStream fileStream = File.Create(myNetworkPath)) { var file = System.Text.Encoding.UTF8.GetBytes("this is a test"); fileStream.Write(file, 0, file.Length); fileStream.Flush(); fileStream.Close(); } } } catch (Exception ex) { } } } }
这样就可以访问和读取网络中的路径了,在测试中一直遇到在调用wnetaddconnection2方法的时候返回error 53的错误,看代码中也是没有错误,直接访问所用的测试目标网络文件也是可以的,然后再google一搜,就是我们在传递网络目标文件路径的时候后面不能有“\”,把“\”去掉然后再访问就没有问题了。
原文链接https://social.msdn.microsoft.com/Forums/windows/en-US/5f8224d4-c36a-4051-a8e5-7b2e4d817986/wnetaddconnection2-fails-with-error-code-53?forum=peertopeer。