【截止2014-10-14】
网上搜索了很多篇文章,所提及的总共有两种方式:
1.Asp.Net模拟登陆;
例如:
实现一个2008serve的IIS的虚拟目录(通过网络路径(UNC)的形式,共享在另外一个2008服务器上
2.调用Windows API 的 WNetAddConnection2 、WNetCancelConnection2函数;
例如:
相对来说,第一种方式是最直接的,且改动较小的。但不足之处就是比较依赖共享所在服务器(如果切换共享服务器地址,那么本地的用户名和密码都要作调整。);
而第二种方式缺点(个人感觉),API函数的不稳定、链接数超出限制、内存泄露等不稳定的问题(如果有哪位朋友有解决方案,还请告知,谢谢)。
ps:折腾了两天,先用第一种方式吧。附上一个第二种方式的辅助类。
1 #define CheckReturn 2 using System; 3 using System.Collections.Generic; 4 using System.Text; 5 using System.Runtime.InteropServices; 6 7 8 /// <summary> 9 /// 网络资源访问 10 /// </summary> 11 public class WNetConnectionHelper : IDisposable 12 { 13 14 /// <summary> 15 /// 添加远程网络连接。 16 /// </summary> 17 /// <param name="lpNetResource">是一个包含网络访问资源的结构,在这里作为参数用来指定详细的网络连接信息</param> 18 /// <param name="lpPassword">指出访问远程计算机的密码。在Windows 95/98/Me 系统中,该值必须设置为NULL或空字符串</param> 19 /// <param name="lpUsername">指出访问远程计算机的用户名。在Windows 95/98/Me 系统中,该值必须设置为NULL或空字符串</param> 20 /// <param name="dwFlags">指出连接选项,包含六种设置</param> 21 /// <returns>如果方法执行成功返回“NO_ERROR”即“0”。如果执行失败返回System Error Code。</returns> 22 [DllImport("Mpr.dll", EntryPoint = "WNetAddConnection2")] 23 /* 24 private static extern uint WNetAddConnection2(NetResource lpNetResource, [MarshalAs(UnmanagedType.LPStr)]string lpPassword, [MarshalAs(UnmanagedType.LPStr)]string lpUsername, uint dwFlags); 25 */ 26 private static extern uint WNetAddConnection2(IntPtr lpNetResource, string lpPassword, string lpUsername, uint dwFlags); 27 28 /// <summary> 29 /// 释放存在的网络连接。 30 /// </summary> 31 /// <param name="lpName">指定本地驱动器或远程共享资源</param> 32 /// <param name="dwFlags">表示断开连接方式。设置 0 或CONNECT_UPDATE_PROFILE。</param> 33 /// <param name="fForce">如果当前正在使用远程资源,是否进行强制断开连接。如果设置FALSE,在有远程资源使用的情况下关闭连接操作将会失败。</param> 34 /// <returns>如果方法执行成功返回“NO_ERROR”即“0”。如果执行失败返回System Error Code。</returns> 35 [DllImport("Mpr.dll", EntryPoint = "WNetCancelConnection2")] 36 private static extern uint WNetCancelConnection2([MarshalAs(UnmanagedType.LPStr)]string lpName, uint dwFlags, int fForce); 37 38 39 /// <summary> 40 /// 获取网络错误的扩展错误信息 41 /// </summary> 42 /// <param name="lpError">指定一个变量,用于装载网络错误代码。具体的代码由网络供应商决定</param> 43 /// <param name="lpErrorBuf">指定一个字串缓冲区,用于装载网络错误的说明</param> 44 /// <param name="nErrorBufSize">lpErrorBuf缓冲区包含的字符数量</param> 45 /// <param name="lpNameBuf">用于装载网络供应商名字的字串缓冲区</param> 46 /// <param name="nNameBufSize">lpNameBuf缓冲区的字符数量</param> 47 /// <returns></returns> 48 [DllImport("Mpr.dll", EntryPoint = "WNetGetLastError")] 49 private static extern uint WNetGetLastError(ref uint lpError, [MarshalAs(UnmanagedType.LPStr)]ref string lpErrorBuf, long nErrorBufSize, [MarshalAs(UnmanagedType.LPStr)]ref string lpNameBuf, uint nNameBufSize); 50 51 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] 52 public struct NetResource 53 { 54 /// <summary> 55 /// 指定枚举范围。设置RESOURCE_CONNECTED,RESOURCE_GLOBALNET,RESOURCE_REMEMBERED三值之一。 56 /// </summary> 57 public int dwScope; 58 /// <summary> 59 /// 指定访问的资源类型。设置三个值之一。RESOURCETYPE_ANY表示所有资源;RESOURCETYPE_DISK表示磁盘资源;RESOURCETYPE_PRINT表示打印机。 60 /// </summary> 61 public int dwType; 62 /// <summary> 63 /// 指出资源显示类型。RESOURCEDISPLAYTYPE_DOMAIN;RESOURCEDISPLAYTYPE_SERVER;RESOURCEDISPLAYTYPE_SHARE;RESOURCEDISPLAYTYPE_GENERIC。 64 /// </summary> 65 public int dwDisplayType; 66 /// <summary> 67 /// 描述资源的使用方式。设置RESOURCEUSAGE_CONNECTABLE 或RESOURCEUSAGE_CONTAINER。 68 /// </summary> 69 public int dwUsage; 70 /// <summary> 71 /// 同dwScope关联,指定本地映射。 72 /// </summary> 73 //[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] 74 public string lpLocalName; 75 /// <summary> 76 /// 远程访问文件夹路径。 77 /// </summary> 78 //[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] 79 public string lpRemoteName; 80 /// <summary> 81 /// 描述。 82 /// </summary> 83 //[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] 84 public string lpComment; 85 /// <summary> 86 /// 资源提供者,可以设置为NULL。 87 /// </summary> 88 //[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] 89 public string lpProvider; 90 } 91 92 93 public enum RESOURCE_SCOPE 94 { 95 RESOURCE_CONNECTED = 1, 96 RESOURCE_GLOBALNET = 2, 97 RESOURCE_REMEMBERED = 3, 98 RESOURCE_RECENT = 4, 99 RESOURCE_CONTEXT = 5 100 } 101 102 public enum RESOURCE_TYPE 103 { 104 RESOURCETYPE_ANY = 0, 105 RESOURCETYPE_DISK = 1, 106 RESOURCETYPE_PRINT = 2, 107 RESOURCETYPE_RESERVED = 8, 108 } 109 110 public enum RESOURCE_USAGE 111 { 112 RESOURCEUSAGE_CONNECTABLE = 1, 113 RESOURCEUSAGE_CONTAINER = 2, 114 RESOURCEUSAGE_NOLOCALDEVICE = 4, 115 RESOURCEUSAGE_SIBLING = 8, 116 RESOURCEUSAGE_ATTACHED = 16, 117 RESOURCEUSAGE_ALL = (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED), 118 } 119 120 public enum RESOURCE_DISPLAYTYPE 121 { 122 RESOURCEDISPLAYTYPE_GENERIC = 0, 123 RESOURCEDISPLAYTYPE_DOMAIN = 1, 124 RESOURCEDISPLAYTYPE_SERVER = 2, 125 RESOURCEDISPLAYTYPE_SHARE = 3, 126 RESOURCEDISPLAYTYPE_FILE = 4, 127 RESOURCEDISPLAYTYPE_GROUP = 5, 128 RESOURCEDISPLAYTYPE_NETWORK = 6, 129 RESOURCEDISPLAYTYPE_ROOT = 7, 130 RESOURCEDISPLAYTYPE_SHAREADMIN = 8, 131 RESOURCEDISPLAYTYPE_DIRECTORY = 9, 132 RESOURCEDISPLAYTYPE_TREE = 10, 133 RESOURCEDISPLAYTYPE_NDSCONTAINER = 11 134 } 135 136 137 /// <summary> 138 /// 添加远程网络连接。 139 /// </summary> 140 /// <param name="netResource">是一个包含网络访问资源的结构,在这里作为参数用来指定详细的网络连接信息</param> 141 /// <param name="username">指出访问远程计算机的用户名。在Windows 95/98/Me 系统中,该值必须设置为NULL或空字符串</param> 142 /// <param name="password">指出访问远程计算机的密码。在Windows 95/98/Me 系统中,该值必须设置为NULL或空字符串</param> 143 /// <returns>如果方法执行成功返回“NO_ERROR”即“0”。如果执行失败返回System Error Code。</returns> 144 public static uint WNetAddConnection(NetResource netResource, string username, string password) 145 { 146 IntPtr ptr_netResource = IntPtr.Zero; 147 try 148 { 149 //分配内存 150 ptr_netResource = System.Runtime.InteropServices.Marshal.AllocHGlobal(System.Runtime.InteropServices.Marshal.SizeOf(netResource)); 151 System.Runtime.InteropServices.Marshal.StructureToPtr(netResource, ptr_netResource, false); 152 153 uint result = WNetAddConnection2(ptr_netResource, password, username, 0); 154 return result; 155 } 156 finally 157 { 158 if (ptr_netResource != IntPtr.Zero) 159 System.Runtime.InteropServices.Marshal.FreeCoTaskMem(ptr_netResource); 160 } 161 /* 162 uint result = WNetAddConnection2(netResource, password, username, 0); 163 return result; 164 */ 165 } 166 167 /// <summary> 168 /// 添加远程网络连接。 169 /// </summary> 170 /// <param name="username">指出访问远程计算机的用户名。在Windows 95/98/Me 系统中,该值必须设置为NULL或空字符串</param> 171 /// <param name="password">指出访问远程计算机的密码。在Windows 95/98/Me 系统中,该值必须设置为NULL或空字符串</param> 172 /// <param name="remoteName">远程访问文件夹路径。</param> 173 /// <param name="localName">同dwScope关联,指定本地映射。</param> 174 /// <returns>如果方法执行成功返回“NO_ERROR”即“0”。如果执行失败返回System Error Code。</returns> 175 public static uint WNetAddConnection(string username, string password, string remoteName, string localName) 176 { 177 NetResource netResource = new NetResource(); 178 netResource.dwScope = 2; //RESOURCE_GLOBALNET 179 netResource.dwType = 1; //RESOURCETYPE_DISK 180 netResource.dwDisplayType = 3; //RESOURCEDISPLAYTYPE_SHARE 181 netResource.dwUsage = 1; //RESOURCEUSAGE_CONNECTABLE 182 netResource.lpLocalName = localName; 183 netResource.lpRemoteName = remoteName.TrimEnd('/'); 184 //netResource.lpRemoteName = lpComment; 185 //netResource.lpProvider = null; 186 uint result = WNetAddConnection(netResource, username, password); 187 return result; 188 } 189 190 /// <summary> 191 /// 添加远程网络连接。 192 /// </summary> 193 /// <param name="name">指定本地驱动器或远程共享资源</param> 194 /// <param name="flags">表示断开连接方式。设置 0 或CONNECT_UPDATE_PROFILE。</param> 195 /// <param name="force">如果当前正在使用远程资源,是否进行强制断开连接。如果设置FALSE,在有远程资源使用的情况下关闭连接操作将会失败。</param> 196 /// <returns>如果方法执行成功返回“NO_ERROR”即“0”。如果执行失败返回System Error Code。</returns> 197 public static uint WNetCancelConnection(string name, uint flags, bool force) 198 { 199 uint nret = WNetCancelConnection2(name, flags, force ? 1 : 0); 200 return nret; 201 } 202 203 204 #region SelfUsing 205 bool connectSuccess = false; 206 string username, password, remoteName, localName; 207 private WNetConnectionHelper(string username, string password, string remoteName, string localName) 208 { 209 this.username = username; 210 this.password = password; 211 this.remoteName = remoteName; 212 this.localName = localName; 213 Close(); 214 var code = WNetAddConnection(username, password, remoteName, localName); 215 connectSuccess = code == 0; 216 #if CheckReturn 217 218 if (code != 0) 219 { 220 GetLastError(); 221 222 throw new InvalidOperationException("The method WNetAddConnection return " + code); 223 } 224 #endif 225 } 226 227 private static void GetLastError() 228 { 229 uint lpError = 0; 230 string lpErrorBuf = null; 231 uint nErrorBufSize = 1024; 232 string lpNameBuf = null; 233 uint nNameBufSize = 1024; 234 var errCode = WNetGetLastError(ref lpError, ref lpErrorBuf, nErrorBufSize, ref lpNameBuf, nNameBufSize); 235 } 236 237 public static WNetConnectionHelper New(string username, string password, string remoteName, string localName) 238 { 239 if (string.IsNullOrEmpty(remoteName)) 240 throw new ArgumentException("remoteName"); 241 return new WNetConnectionHelper(username, password, remoteName.TrimEnd('/'), localName); 242 } 243 244 245 #endregion 246 247 #region IDisposable 成员 248 249 public void Dispose() 250 { 251 if (!connectSuccess) return; 252 if (string.IsNullOrEmpty(remoteName)) return; 253 var code = Close(); 254 #if CheckReturn 255 if (code != 0) 256 { 257 GetLastError(); 258 throw new InvalidOperationException("The method WNetCancelConnection return " + code); 259 260 } 261 #endif 262 } 263 264 private uint Close() 265 { 266 267 return WNetCancelConnection(remoteName, 1, true); 268 } 269 270 #endregion 271 }