摘要:
本文簡單介紹在.NET中如何
通過API實現局域網共享訪問編程
。
本頁內容
一般用戶在訪問局域網中的計算機時都需要提供訪問憑據,如果想通過編程來實現自動登錄,.NET開發人員一般首先會想到通過調用WMI來實現。但是在實現過程中也許你會發現使用ConnectionOptions類不是很理想,因此本文采用了平台調用的方式來介紹共享訪問編程實現。
mpr.dll
是Windws操作系統網絡通訊相關模塊,通過對功能需求的分析,直接調用mpr.dll來實現該功能。在.NET中需要通過平台調用(platform invoke)來調用其中的方法,這里需要用到mpr.dll中的兩個方法。對於mpr.dll中包含的具體功能這里不進行闡述,大家通過MSDN可以找到詳細說明,這里只列出方法定義。
DWORD WNetAddConnection2(
LPNETRESOURCE lpNetResource,
LPCTSTR lpPassword,
LPCTSTR lpUsername,
DWORD dwFlags
);
|
該方法主要功能是添加遠程網絡連接。
參數描述如下:
lpNetResource
:是一個包含網絡訪問資源的結構,在這里作為參數用來指定詳細的網絡連接信息,具體請看下面。
lpPassword
:指出訪問遠程計算機的密碼。在Windows 95/98/Me 系統中,該值必須設置為NULL或空字符串。
lpUsername
:指出訪問遠程計算機的用戶名。在Windows 95/98/Me 系統中,該值必須設置為NULL或空字符串。
dwFlags
:指出連接選項,包含六種設置,具體可以看MSDN。
NETRESOURCE
結構通過多個字段指定網絡連接資源信息。定義如下:
typedef struct _NETRESOURCE {
DWORD dwScope;
DWORD dwType;
DWORD dwDisplayType;
DWORD dwUsage;
LPTSTR lpLocalName;
LPTSTR lpRemoteName;
LPTSTR lpComment;
LPTSTR lpProvider;
} NETRESOURCE;
|
各個成員描述如下:
dwScope
:指定枚舉范圍。設置RESOURCE_CONNECTED,RESOURCE_GLOBALNET,RESOURCE_REMEMBERED三值之一。
dwType
:指定訪問的資源類型。設置三個值之一。RESOURCETYPE_ANY表示所有資源;RESOURCETYPE_DISK表示磁盤資源;RESOURCETYPE_PRINT表示打印機。
dwDisplayType
:指出資源顯示類型。RESOURCEDISPLAYTYPE_DOMAIN;RESOURCEDISPLAYTYPE_SERVER;RESOURCEDISPLAYTYPE_SHARE;RESOURCEDISPLAYTYPE_GENERIC。
dwUsage
:描述資源的使用方式。設置RESOURCEUSAGE_CONNECTABLE 或RESOURCEUSAGE_CONTAINER。
lpLocalName
:同dwScope關聯,指定本地映射。
lpRemoteName
:遠程訪問文件夾路徑。
lpComment
:描述。
lpProvider
:資源提供者,可以設置為NULL。
DWORD WNetCancelConnection2(
LPCTSTR lpName,
DWORD dwFlags,
BOOL fForce
);
|
通過該方法實現釋放存在的網絡連接。
各成員描述如下:
lpName
:指定本地驅動器或遠程共享資源
dwFlags
:表示斷開連接方式。設置 0 或CONNECT_UPDATE_PROFILE。
fForce
:如果當前正在使用遠程資源,是否進行強制斷開連接。如果設置FALSE,在有遠程資源使用的情況下關閉連接操作將會失敗。
針對以上兩個方法,有些System Error Code返回值並不意味遠程資源不可以訪問。
例如:
ERROR_SESSION_CREDENTIAL_CONFLICT
1219
Multiple connections to a server or shared resource by the same user, using more than one user name, are not allowed. Disconnect all previous connections to the server or shared resource and try again.
ERROR_REMOTE_SESSION_LIMIT_EXCEEDED
1220
An attempt was made to establish a session to a network server, but there are already too many sessions established to that server.
為便於在.NET環境中使用,本文寫了一個WNetConnectionHelper靜態類,對這些方法進行包裝。
P/Invoke
需要引用
System.Runtime.InteropServices
命名空間。
由於代碼簡短,下面給出完整實現代碼。
public
static class WNetConnectionHelper
{
[DllImport("mpr.dll", EntryPoint = "WNetAddConnection2")]
private static extern uint WNetAddConnection2(NetResource lpNetResource, string lpPassword, string lpUsername, uint dwFlags);
[DllImport("Mpr.dll", EntryPoint = "WNetCancelConnection2"))]
private static extern uint WNetCancelConnection2(string lpName, uint dwFlags, bool fForce);
[StructLayout(LayoutKind.Sequential)]
public class NetResource
{
public int dwScope;
public int dwType;
public int dwDisplayType;
public int dwUsage;
public string lpLocalName;
public string lpRemoteName;
public string lpComment;
public string lpProvider;
}
public static uint WNetAddConnection(NetResource netResource,string username,string password)
{
uint result = WNetAddConnection2(netResource, password, username, 0);
return result;
}
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_ANY
netResource.dwDisplayType = 3; //RESOURCEDISPLAYTYPE_GENERIC
netResource.dwUsage = 1; //RESOURCEUSAGE_CONNECTABLE
netResource.lpLocalName = localName;
netResource.lpRemoteName = remoteName.TrimEnd('//');
//netResource.lpRemoteName = lpComment;
//netResource.lpProvider = null;
uint result = WNetAddConnection2(netResource, password, username, 0);
return result;
}
public static uint WNetCancelConnection(string name,uint flags,bool force)
{
uint nret = WNetCancelConnection2(name, flags, force);
return nret;
}
}
|
最后,通過兩個簡單示例來演示
WNetConnectionHelper
類的使用
。
a
.列舉遠程計算機共享文件夾資源。代碼如下:
try
{
string
result = WNetConnectionHelper.WNetAddConnection("192.120.40.10//ShareUser", "xxxxxx", @"//192.120.40.10/test", null);
string
[] files = Directory.GetFiles(@"//192.120.40.56/test/fw");
string
s1 = GetFile(@"//192.120.40.10/test/fw/test.doc");
uint
n = WNetConnectionHelper.WNetCancelConnection("//192.120.40.10//test", 1, true);
}
catch
(Exception ex)
{
//
編寫異常處理代碼
}
|
b.
另一個比較常見的應用是在ASP.NET服務器端訪問其他計算機的資源,比如文檔服務器,然后通過Web頁面輸出。
主要示例代碼如下:
protected
void Page_Load(object sender, EventArgs e)
{
uint r = WNetConnectionHelper.WNetAddConnection("192.120.40.10//username", "password", @"//192.120.40.10/test", "Z:");
string filename = @"//192.120.40.10/test/fw/1.doc";
ReadFile(filename);
}
寫文件到Web輸出:
public
void ReadFile(string filename)
{
Response.Clear();
Response.Charset = "utf-8";
Response.Buffer = true;
this.EnableViewState = false;
Response.ContentType = "application/ms-word";
Response.ContentEncoding = System.Text.Encoding.UTF8;
Response.AppendHeader("Content-Disposition", "inline;filename=1.doc");
try
{
Response.WriteFile(filename, true);
}
catch (Exception ex)
{
Response.Write(ex.ToString());
}
Response.Flush();
}
|
以上方法對於大文件使用Response.WriteFile方法會有些問題,在實際編程中需要做優化處理。
本文中的有些功能描述可能不夠具體或妥當,如果需要了解mpr.dll的更多功能還是建議看MSDN文檔。對於WNetConnectionHelper的實現存在一些需要完善的地方,不過對於一般的應用基本可以滿足,在實際使用時還需要考慮多線程的情況。另外,在有同名驅動器映射的情況下需要做一些判斷,而且弄清楚System Error Code的含義對代碼的調試及正確執行有很大的幫助。This is some sample text. You are usingFCKeditor.
第二種方法是通過:cmd->net use 輸入一次用戶名和密碼后,客戶端訪問共享文件就不用再輸入密碼 命令:“net use \\192.168.39.178 "admin" /user:"admin"”
using System.Diagnostics;
Process prc = new Process();
prc.StartInfo.FileName = @ "cmd.exe ";
prc.StartInfo.UseShellExecute = false;
prc.StartInfo.RedirectStandardInput = true;
prc.StartInfo.RedirectStandardOutput = true;
prc.StartInfo.RedirectStandardError = true;
prc.StartInfo.CreateNoWindow = false;
prc.Start();
string cmd = @ "net use z: \\192.168.1.1\tmp ""pass"" /user:""name""";
Process prc = new Process();
prc.StartInfo.FileName = @ "cmd.exe ";
prc.StartInfo.UseShellExecute = false;
prc.StartInfo.RedirectStandardInput = true;
prc.StartInfo.RedirectStandardOutput = true;
prc.StartInfo.RedirectStandardError = true;
prc.StartInfo.CreateNoWindow = false;
prc.Start();
string cmd = @ "net use z: \\192.168.1.1\tmp ""pass"" /user:""name""";
//"pass"連接服務器的密碼 user:"name"用戶名
//
Process.Start( "net ",@ "use z: \\192.168.1.1\tmp " "pass " " /user: " "name " " ");
prc.StandardInput.WriteLine(cmd);
prc.StandardInput.Close();
prc.StandardInput.WriteLine(cmd);
prc.StandardInput.Close();