IIS/ASP.NET访问共享文件夹的可用方式

【截止2014-10-14】

 

网上搜索了很多篇文章,所提及的总共有两种方式:

  1. 1.Asp.Net模拟登陆;

例如:

实战ASP.NET访问共享文件夹(含详细操作步骤)

实现一个2008serve的IIS的虚拟目录(通过网络路径(UNC)的形式,共享在另外一个2008服务器上

 

  1. 2.调用Windows API 的 WNetAddConnection2 、WNetCancelConnection2函数;

例如:

ASP.NET网络映射驱动器无权限访问的解决方案
ASP.NET访问网络驱动器(映射磁盘)

共享访问在.NET中的编程实现

 

 

相对来说,第一种方式是最直接的,且改动较小的。但不足之处就是比较依赖共享所在服务器(如果切换共享服务器地址,那么本地的用户名和密码都要作调整。);

而第二种方式缺点(个人感觉),API函数的不稳定、链接数超出限制、内存泄露等不稳定的问题(如果有哪位朋友有解决方案,还请告知,谢谢)。

 

ps:折腾了两天,先用第一种方式吧。附上一个第二种方式的辅助类。

 

 

#define CheckReturn
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;


/// <summary>
/// 网络资源访问
/// </summary>
public class WNetConnectionHelper : IDisposable
{

    /// <summary>
    /// 添加远程网络连接。
    /// </summary>
    /// <param name="lpNetResource">是一个包含网络访问资源的结构,在这里作为参数用来指定详细的网络连接信息</param>
    /// <param name="lpPassword">指出访问远程计算机的密码。在Windows 95/98/Me 系统中,该值必须设置为NULL或空字符串</param>
    /// <param name="lpUsername">指出访问远程计算机的用户名。在Windows 95/98/Me 系统中,该值必须设置为NULL或空字符串</param>
    /// <param name="dwFlags">指出连接选项,包含六种设置</param>
    /// <returns>如果方法执行成功返回“NO_ERROR”即“0”。如果执行失败返回System Error Code。</returns>
    [DllImport("Mpr.dll", EntryPoint = "WNetAddConnection2")]
    /*
    private static extern uint WNetAddConnection2(NetResource lpNetResource, [MarshalAs(UnmanagedType.LPStr)]string lpPassword, [MarshalAs(UnmanagedType.LPStr)]string lpUsername, uint dwFlags);
    */
    private static extern uint WNetAddConnection2(IntPtr lpNetResource, string lpPassword, string lpUsername, uint dwFlags);

    /// <summary>
    /// 释放存在的网络连接。
    /// </summary>
    /// <param name="lpName">指定本地驱动器或远程共享资源</param>
    /// <param name="dwFlags">表示断开连接方式。设置 0 或CONNECT_UPDATE_PROFILE。</param>
    /// <param name="fForce">如果当前正在使用远程资源,是否进行强制断开连接。如果设置FALSE,在有远程资源使用的情况下关闭连接操作将会失败。</param>
    /// <returns>如果方法执行成功返回“NO_ERROR”即“0”。如果执行失败返回System Error Code。</returns>
    [DllImport("Mpr.dll", EntryPoint = "WNetCancelConnection2")]
    private static extern uint WNetCancelConnection2([MarshalAs(UnmanagedType.LPStr)]string lpName, uint dwFlags, int fForce);


    /// <summary>
    /// 获取网络错误的扩展错误信息
    /// </summary>
    /// <param name="lpError">指定一个变量,用于装载网络错误代码。具体的代码由网络供应商决定</param>
    /// <param name="lpErrorBuf">指定一个字串缓冲区,用于装载网络错误的说明</param>
    /// <param name="nErrorBufSize">lpErrorBuf缓冲区包含的字符数量</param>
    /// <param name="lpNameBuf">用于装载网络供应商名字的字串缓冲区</param>
    /// <param name="nNameBufSize">lpNameBuf缓冲区的字符数量</param>
    /// <returns></returns>
    [DllImport("Mpr.dll", EntryPoint = "WNetGetLastError")]
    private static extern uint WNetGetLastError(ref uint lpError, [MarshalAs(UnmanagedType.LPStr)]ref string lpErrorBuf, long nErrorBufSize, [MarshalAs(UnmanagedType.LPStr)]ref  string lpNameBuf, uint nNameBufSize);

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
    public struct NetResource
    {
        /// <summary>
        /// 指定枚举范围。设置RESOURCE_CONNECTED,RESOURCE_GLOBALNET,RESOURCE_REMEMBERED三值之一。
        /// </summary>
        public int dwScope;
        /// <summary>
        /// 指定访问的资源类型。设置三个值之一。RESOURCETYPE_ANY表示所有资源;RESOURCETYPE_DISK表示磁盘资源;RESOURCETYPE_PRINT表示打印机。
        /// </summary>
        public int dwType;
        /// <summary>
        /// 指出资源显示类型。RESOURCEDISPLAYTYPE_DOMAIN;RESOURCEDISPLAYTYPE_SERVER;RESOURCEDISPLAYTYPE_SHARE;RESOURCEDISPLAYTYPE_GENERIC。
        /// </summary>
        public int dwDisplayType;
        /// <summary>
        /// 描述资源的使用方式。设置RESOURCEUSAGE_CONNECTABLE 或RESOURCEUSAGE_CONTAINER。
        /// </summary>
        public int dwUsage;
        /// <summary>
        /// 同dwScope关联,指定本地映射。
        /// </summary>
        //[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public string lpLocalName;
        /// <summary>
        /// 远程访问文件夹路径。
        /// </summary>
        //[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public string lpRemoteName;
        /// <summary>
        /// 描述。
        /// </summary>
        //[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public string lpComment;
        /// <summary>
        /// 资源提供者,可以设置为NULL。
        /// </summary>
        //[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public string lpProvider;
    }


    public enum RESOURCE_SCOPE
    {
        RESOURCE_CONNECTED = 1,
        RESOURCE_GLOBALNET = 2,
        RESOURCE_REMEMBERED = 3,
        RESOURCE_RECENT = 4,
        RESOURCE_CONTEXT = 5
    }

    public enum RESOURCE_TYPE
    {
        RESOURCETYPE_ANY = 0,
        RESOURCETYPE_DISK = 1,
        RESOURCETYPE_PRINT = 2,
        RESOURCETYPE_RESERVED = 8,
    }

    public enum RESOURCE_USAGE
    {
        RESOURCEUSAGE_CONNECTABLE = 1,
        RESOURCEUSAGE_CONTAINER = 2,
        RESOURCEUSAGE_NOLOCALDEVICE = 4,
        RESOURCEUSAGE_SIBLING = 8,
        RESOURCEUSAGE_ATTACHED = 16,
        RESOURCEUSAGE_ALL = (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED),
    }

    public enum RESOURCE_DISPLAYTYPE
    {
        RESOURCEDISPLAYTYPE_GENERIC = 0,
        RESOURCEDISPLAYTYPE_DOMAIN = 1,
        RESOURCEDISPLAYTYPE_SERVER = 2,
        RESOURCEDISPLAYTYPE_SHARE = 3,
        RESOURCEDISPLAYTYPE_FILE = 4,
        RESOURCEDISPLAYTYPE_GROUP = 5,
        RESOURCEDISPLAYTYPE_NETWORK = 6,
        RESOURCEDISPLAYTYPE_ROOT = 7,
        RESOURCEDISPLAYTYPE_SHAREADMIN = 8,
        RESOURCEDISPLAYTYPE_DIRECTORY = 9,
        RESOURCEDISPLAYTYPE_TREE = 10,
        RESOURCEDISPLAYTYPE_NDSCONTAINER = 11
    }


    /// <summary>
    /// 添加远程网络连接。
    /// </summary>
    /// <param name="netResource">是一个包含网络访问资源的结构,在这里作为参数用来指定详细的网络连接信息</param>
    /// <param name="username">指出访问远程计算机的用户名。在Windows 95/98/Me 系统中,该值必须设置为NULL或空字符串</param>
    /// <param name="password">指出访问远程计算机的密码。在Windows 95/98/Me 系统中,该值必须设置为NULL或空字符串</param>
    /// <returns>如果方法执行成功返回“NO_ERROR”即“0”。如果执行失败返回System Error Code。</returns>
    public static uint WNetAddConnection(NetResource netResource, string username, string password)
    {
        IntPtr ptr_netResource = IntPtr.Zero;
        try
        {
            //分配内存
            ptr_netResource = System.Runtime.InteropServices.Marshal.AllocHGlobal(System.Runtime.InteropServices.Marshal.SizeOf(netResource));
            System.Runtime.InteropServices.Marshal.StructureToPtr(netResource, ptr_netResource, false);

            uint result = WNetAddConnection2(ptr_netResource, password, username, 0);
            return result;
        }
        finally
        {
            if (ptr_netResource != IntPtr.Zero)
                System.Runtime.InteropServices.Marshal.FreeCoTaskMem(ptr_netResource);
        }
        /*
        uint result = WNetAddConnection2(netResource, password, username, 0);
        return result;
        */
    }

    /// <summary>
    /// 添加远程网络连接。
    /// </summary>
    /// <param name="username">指出访问远程计算机的用户名。在Windows 95/98/Me 系统中,该值必须设置为NULL或空字符串</param>
    /// <param name="password">指出访问远程计算机的密码。在Windows 95/98/Me 系统中,该值必须设置为NULL或空字符串</param>
    /// <param name="remoteName">远程访问文件夹路径。</param>
    /// <param name="localName">同dwScope关联,指定本地映射。</param>
    /// <returns>如果方法执行成功返回“NO_ERROR”即“0”。如果执行失败返回System Error Code。</returns>
    public static uint WNetAddConnection(string username, string password, string remoteName, string localName)
    {
        NetResource netResource = new NetResource();
        netResource.dwScope = 2;       //RESOURCE_GLOBALNET
        netResource.dwType = 1;       //RESOURCETYPE_DISK
        netResource.dwDisplayType = 3; //RESOURCEDISPLAYTYPE_SHARE
        netResource.dwUsage = 1;       //RESOURCEUSAGE_CONNECTABLE
        netResource.lpLocalName = localName;
        netResource.lpRemoteName = remoteName.TrimEnd(/);
        //netResource.lpRemoteName = lpComment;
        //netResource.lpProvider = null;
        uint result = WNetAddConnection(netResource, username, password);
        return result;
    }

    /// <summary>
    /// 添加远程网络连接。
    /// </summary>
    /// <param name="name">指定本地驱动器或远程共享资源</param>
    /// <param name="flags">表示断开连接方式。设置 0 或CONNECT_UPDATE_PROFILE。</param>
    /// <param name="force">如果当前正在使用远程资源,是否进行强制断开连接。如果设置FALSE,在有远程资源使用的情况下关闭连接操作将会失败。</param>
    /// <returns>如果方法执行成功返回“NO_ERROR”即“0”。如果执行失败返回System Error Code。</returns>
    public static uint WNetCancelConnection(string name, uint flags, bool force)
    {
        uint nret = WNetCancelConnection2(name, flags, force ? 1 : 0);
        return nret;
    }


    #region SelfUsing
    bool connectSuccess = false;
    string username, password, remoteName, localName;
    private WNetConnectionHelper(string username, string password, string remoteName, string localName)
    {
        this.username = username;
        this.password = password;
        this.remoteName = remoteName;
        this.localName = localName;
        Close();
        var code = WNetAddConnection(username, password, remoteName, localName);
        connectSuccess = code == 0;
#if CheckReturn

        if (code != 0)
        {
            GetLastError();

            throw new InvalidOperationException("The method WNetAddConnection return " + code);
        }
#endif
    }

    private static void GetLastError()
    {
        uint lpError = 0;
        string lpErrorBuf = null;
        uint nErrorBufSize = 1024;
        string lpNameBuf = null;
        uint nNameBufSize = 1024;
        var errCode = WNetGetLastError(ref lpError, ref lpErrorBuf, nErrorBufSize, ref lpNameBuf, nNameBufSize);
    }

    public static WNetConnectionHelper New(string username, string password, string remoteName, string localName)
    {
        if (string.IsNullOrEmpty(remoteName))
            throw new ArgumentException("remoteName");
        return new WNetConnectionHelper(username, password, remoteName.TrimEnd(/), localName);
    }


    #endregion

    #region IDisposable 成员

    public void Dispose()
    {
        if (!connectSuccess) return;
        if (string.IsNullOrEmpty(remoteName)) return;
        var code = Close();
#if CheckReturn
        if (code != 0)
        {
            GetLastError();
            throw new InvalidOperationException("The method WNetCancelConnection return " + code);

        }
#endif
    }

    private uint Close()
    {

        return WNetCancelConnection(remoteName, 1, true);
    }

    #endregion
}

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。