公司一个网站提供用户下载功能,但是文件不在网站服务器(WINDOWS SERVER 2003),而是在另一台服务器(WINDOWS SERVER 2003)上,需要建立映射盘,然后读取文件列表,供用户下载。
很简单的功能,本来没什么可写的,但是在本机(WINDOWS XP)开发完成之后,测试一切正常,发布到服务器之后却没有文件列表,查了一下日志,错误提示是没有找到映射盘的盘符,上网查了一下,都说映射盘可以直接像本地磁盘一样访问的,奇怪了。
想好好久,考虑到本机和服务器的操作系统不同,最大的区别是WINDOWS SERVER 2003是多用户机制,会不会是用当前用户建立的磁盘映射其他用户访问不到?后来问了一下系统安全的同事,得到证实,在WINDOWS SERVER 2003是这样的,而且用administrator账户建立的磁盘映射,即使程序给了administrator的执行权限也是访问不到的,因为存在控制台权限的问题,不是在同一个控制台中。
之前在MSDN中找到如下配置:
<authentication mode="Windows"/>
<identity impersonate="true" userName="<domain>/<UserName>" password="<password>"/>
可以使ASP.NET程序以给定的用户名执行,但是我测试之后证实,即使是用administrator账户创建的映射盘程序还是找不到,可能就是上面的控制台问题。
基于以上原因,考虑到如果在读取文件列表时,由应用程序首先建立映射盘,然后再读取,这样可以保证是同一个账户同一个控制台。经测试,此方法可行,下面把关键代码贴出来,以备以后查证。(此代码也是在网络上搜罗的)
#region Windows API enum and struct
public enum ERROR_ID
{
ERROR_SUCCESS = 0, // Success
ERROR_MORE_DATA = 234,
ERROR_NO_BROWSER_SERVERS_FOUND = 6118,
ERROR_INVALID_LEVEL = 124,
ERROR_ACCESS_DENIED = 5,
ERROR_INVALID_PARAMETER = 87,
ERROR_NOT_ENOUGH_MEMORY = 8,
ERROR_NETWORK_BUSY = 54,
ERROR_BAD_NETPATH = 53,
ERROR_NO_NETWORK = 1222,
ERROR_INVALID_HANDLE_STATE = 1609,
ERROR_EXTENDED_ERROR = 1208
}
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
}
[StructLayout(LayoutKind.Sequential)]
public struct NETRESOURCE
{
public RESOURCE_SCOPE dwScope;
public RESOURCE_TYPE dwType;
public RESOURCE_DISPLAYTYPE dwDisplayType;
public RESOURCE_USAGE dwUsage;
[MarshalAs(UnmanagedType.LPStr)]
public string lpLocalName;
[MarshalAs(UnmanagedType.LPStr)]
public string lpRemoteName;
[MarshalAs(UnmanagedType.LPStr)]
public string lpComment;
[MarshalAs(UnmanagedType.LPStr)]
public string lpProvider;
}
#endregion
/** <summary>
/// 连接网络上的共享文件夹
/// </summary>
public class NetworkSharedFolder
{
[DllImport("mpr.dll")]
public static extern int WNetAddConnection2A(NETRESOURCE[] lpNetResource, string lpPassword, string lpUserName, int dwFlags);
[DllImport("mpr.dll")]
public static extern int WNetCancelConnection2A(string sharename, int dwFlags, int fForce);
public static int Connect(string remotePath, string localPath, string username, string password)
{
NETRESOURCE[] share_driver = new NETRESOURCE[1];
share_driver[0].dwType = RESOURCE_TYPE.RESOURCETYPE_DISK;
share_driver[0].lpLocalName = localPath;
share_driver[0].lpRemoteName = remotePath;
Disconnect(localPath);
int ret = WNetAddConnection2A( share_driver, password, username, 1);
return ret;
}
public static void Disconnect(string localpath)
{
WNetCancelConnection2A(localpath, 1, 1);
}
}