最近要实现访问远程主机的共享目录中的一个文件。遇到了权限问题。google了一下,找到了几种解决方法,记录如下:
一、调用Net use命令
// 使用方法: //if (Connect("192.168.1.48", "用户名", "密码")) //{ // File.Copy(@"\\192.168.1.48\共享目录\test.txt", @"e:\\test.txt", true); //} public bool Connect(string remoteHost, string userName, string passWord) { bool Flag = true; Process proc = new Process(); proc.StartInfo.FileName = "cmd.exe"; proc.StartInfo.UseShellExecute = false; proc.StartInfo.RedirectStandardInput = true; proc.StartInfo.RedirectStandardOutput = true; proc.StartInfo.RedirectStandardError = true; proc.StartInfo.CreateNoWindow = true; try { proc.Start(); string command = @"net use \\" + remoteHost + " " + passWord + " " + " /user:" + userName + ">NUL"; proc.StandardInput.WriteLine(command); command = "exit"; proc.StandardInput.WriteLine(command); while (proc.HasExited == false) { proc.WaitForExit(1000); } string errormsg = proc.StandardError.ReadToEnd(); if (errormsg != "") Flag = false; proc.StandardError.Close(); } catch (Exception ex) { Flag = false; } finally { proc.Close(); proc.Dispose(); } return Flag; }
二、调用WNetAddConnection2、WNetAddConnection3或者NetUseAdd函数,进行磁盘映射。
using System;using System.Collections.Generic;using System.Text; using System.Runtime.InteropServices; namespace WindowsApplication1{ public class MyMap { [DllImport("mpr.dll", EntryPoint = "WNetAddConnection2")] public static extern uint WNetAddConnection2( [In] NETRESOURCE lpNetResource, string lpPassword, string lpUsername, uint dwFlags); [DllImport("Mpr.dll")] public 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 LocalName; public string RemoteName; public string Comment; public string Provider; } // remoteNetworkPath format: @"\\192.168.1.48\sharefolder" // localDriveName format: @"E:" public static bool CreateMap(string userName, string password, string remoteNetworkPath, string localDriveName) { NETRESOURCE myNetResource = new NETRESOURCE(); myNetResource.dwScope = 2; //2:RESOURCE_GLOBALNET myNetResource.dwType = 1; //1:RESOURCETYPE_ANY myNetResource.dwDisplayType = 3; //3:RESOURCEDISPLAYTYPE_GENERIC myNetResource.dwUsage = 1; //1: RESOURCEUSAGE_CONNECTABLE myNetResource.LocalName = localDriveName; myNetResource.RemoteName = remoteNetworkPath; myNetResource.Provider = null; uint nret = WNetAddConnection2(myNetResource, password, userName, 0); if (nret == 0) return true; else return false; } // localDriveName format: @"E:" public static bool DeleteMap(string localDriveName) { uint nret = WNetCancelConnection2(localDriveName, 1, true); if (nret == 0) return true; else return false; } public void test() { // 注意: // remote、local、username的格式一定要正确,否则可能出现错误 string remote = @"\\192.168.1.48\generals"; string local = @"P:"; string username = @"Domain\UserName"; string password = @"Password"; bool ret = MyMap.CreateMap(username, password, remote, local); if (ret) { //do what you want: // ... //File.Copy("q:\\test.htm", "c:\\test.htm"); MyMap.DeleteMap(local); } } }}
三、使用WebClient类
由于WebClient类可以上传下载文件,并且支持以http:、https:和file:开头的URI,所以可以用WebClient类来传输文件。
添加System.Net命名空间后使用如下代码下载文件:
private void Test1() { try { WebClient client = new WebClient(); NetworkCredential cred = new NetworkCredential("username", "password", "172.16.0.222"); client.Credentials = cred; client.DownloadFile("file://172.16.0.222/test/111.txt", "111.txt"); } catch (Exception ex) { // 如果网络很慢,而文件又很大,这时可能有超时异常(Time out)。 } } public void Test2() { try { WebClient client = new WebClient(); NetworkCredential cred = new NetworkCredential("username", "password", "domain"); client.Credentials = cred; client.DownloadFile("file://172.16.0.222/test/111.txt", "111.txt"); } catch (Exception ex) { // 如果网络很慢,而文件又很大,这时可能有超时异常(Time out)。 } }
类似的还可以试试WebRequest、FileWebRequest等:
WebRequest req = WebRequest.Create("file://138.12.12.14/generals/test.htm"); NetworkCredential cred = new NetworkCredential("username", "password", "IP"); req.Credentials = cred; WebResponse response = req.GetResponse(); Stream strm = response.GetResponseStream(); StreamReader r = new StreamReader(strm); ... ...
四、角色模拟
/// <summary> /// 身份模拟实现远程资源访问 /// </summary> public class FileImpersonation { // logon types const int LOGON32_LOGON_INTERACTIVE = 2; const int LOGON32_LOGON_NETWORK = 3; const int LOGON32_LOGON_NEW_CREDENTIALS = 9; // logon providers const int LOGON32_PROVIDER_DEFAULT = 0; const int LOGON32_PROVIDER_WINNT50 = 3; const int LOGON32_PROVIDER_WINNT40 = 2; const int LOGON32_PROVIDER_WINNT35 = 1; [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern int LogonUser(string lpszUserName, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern int DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken); [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool RevertToSelf(); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public static extern bool CloseHandle(IntPtr handle); private WindowsImpersonationContext impersonationContext; /// <summary> /// 身份模拟 /// </summary> /// <param name="userName">独立服务器用IP,域环境就用域名</param> /// <param name="domain"></param> /// <param name="password"></param> /// <returns></returns> public bool impersonateValidUser(string userName, string domain, string password) { WindowsIdentity tempWindowsIdentity; IntPtr token = IntPtr.Zero; IntPtr tokenDuplicate = IntPtr.Zero; if (RevertToSelf()) { // 这里使用LOGON32_LOGON_NEW_CREDENTIALS来访问远程资源。 // 如果要(通过模拟用户获得权限)实现服务器程序,访问本地授权数据库可 // 以用LOGON32_LOGON_INTERACTIVE if (LogonUser(userName, domain, password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, ref token) != 0) { if (DuplicateToken(token, 2, ref tokenDuplicate) != 0) { tempWindowsIdentity = new WindowsIdentity(tokenDuplicate); impersonationContext = tempWindowsIdentity.Impersonate(); if (impersonationContext != null) { AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal); IPrincipal pr = System.Threading.Thread.CurrentPrincipal; IIdentity id = pr.Identity; CloseHandle(token); CloseHandle(tokenDuplicate); return true; } } } } if (token != IntPtr.Zero) CloseHandle(token); if (tokenDuplicate != IntPtr.Zero) CloseHandle(tokenDuplicate); return false; } /// <summary> /// 取消模拟身份 /// </summary> public void undoImpersonation() { impersonationContext.Undo(); } /// <summary> /// /// </summary> /// <param name="domain">独立服务器用IP,域环境就用域名</param> /// <param name="username"></param> /// <param name="password"></param> /// <param name="act">需要执行的操作</param> public void ImpersonateFunc(string username, string domain, string password, Action act) { bool isImpersonated = false; try { if (impersonateValidUser(username, domain, password)) { isImpersonated = true; //File.Copy(@"\\192.168.1.48\generals\now.htm", "c:\\now.htm", true); act(); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } finally { if (isImpersonated) undoImpersonation(); } } // } FileImpersonation imp = new FileImpersonation(); imp.ImpersonateFunc("Administrator", "192.168.0.125", "xxxx", () => { var source = new DirectoryInfo(@"D:\HR"); string targetFolder = @"\\192.168.0.125\d$\HR"; if (!Directory.Exists(targetFolder)) { Directory.CreateDirectory(targetFolder); } foreach (FileInfo item in source.GetFiles()) { string targertFile = Path.Combine(targetFolder, item.Name); File.Copy(item.FullName, targertFile, true); } });
五、比较
方法一通过调用Shell命令Net Use实现,有点笨拙。
方法二和方法一有些相似之处。映射远程资源,然后访问。
方法三由于会有超时异常出现,所以在网络速度快、传输小文件时是可以的。
方法四通过身份模拟实现远程资源访问。一些服务器进程就是通过这种方式运行的。这种方法也是我的最爱。
六、要注意的地方
关于这几种方法,google后都可以找到一些文章。但是等到自己实际测试时,有时会出现各种小错误,
这些错误基本来源于两方面:
1、函数的参数选择有问题,和自己的环境不相符。
比如
public static extern int LogonUser(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
中的dwLogonType,要访问远程资源就要用LOGON32_LOGON_NEW_CREDENTIALS,
要模拟本机用户就要用LOGON32_LOGON_INTERACTIVE。
2、函数的参数格式有问题。
a、比如
public static extern int LogonUser(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
中的lpszUserName、lpszDomain、lpszPassword就要写清楚。
我就在这遇到过问题,第一次测试时,远程服务器就是一台独立的文件服务器,这是我的调用方式:
LogonUser("myname", "192.168.1.48", "password", LOGON32_LOGON_NEW_CREDENTIALS,
LOGON32_PROVIDER_DEFAULT, ref token);
第二次测试时,远程服务器是域MyDomain中的一个成员服务器,提供文件服务。这时代码就应该是:
LogonUser("myname", "MyDomain", "password", LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, ref token);
注意,代码中是MyDomain而不是IP地址。
b、再如:
参考上面代码
string remote = @"\\192.168.1.48\generals"; string local = @"P:"; string username = @"Domain\UserName"; string password = @"Password";
如果@"\\192.168.1.48\generals"变成@"\\192.168.1.48\generals\”就会出错;
如果是域中的用户,那么把@"Domain\UserName"变成@"UserName"就会出错。
以上是C#存取遠端主機資源的多種方法分享的詳細內容。更多資訊請關注PHP中文網其他相關文章!

C#在.NET中的編程過程包括以下步驟:1)編寫C#代碼,2)編譯為中間語言(IL),3)由.NET運行時(CLR)執行。 C#在.NET中的優勢在於其現代化語法、強大的類型系統和與.NET框架的緊密集成,適用於從桌面應用到Web服務的各種開發場景。

C#是一種現代、面向對象的編程語言,由微軟開發並作為.NET框架的一部分。 1.C#支持面向對象編程(OOP),包括封裝、繼承和多態。 2.C#中的異步編程通過async和await關鍵字實現,提高應用的響應性。 3.使用LINQ可以簡潔地處理數據集合。 4.常見錯誤包括空引用異常和索引超出範圍異常,調試技巧包括使用調試器和異常處理。 5.性能優化包括使用StringBuilder和避免不必要的裝箱和拆箱。

C#.NET應用的測試策略包括單元測試、集成測試和端到端測試。 1.單元測試確保代碼的最小單元獨立工作,使用MSTest、NUnit或xUnit框架。 2.集成測試驗證多個單元組合的功能,常用模擬數據和外部服務。 3.端到端測試模擬用戶完整操作流程,通常使用Selenium進行自動化測試。

C#高級開發者面試需要掌握異步編程、LINQ、.NET框架內部工作原理等核心知識。 1.異步編程通過async和await簡化操作,提升應用響應性。 2.LINQ以SQL風格操作數據,需注意性能。 3..NET框架的CLR管理內存,垃圾回收需謹慎使用。

C#.NET面試問題和答案包括基礎知識、核心概念和高級用法。 1)基礎知識:C#是微軟開發的面向對象語言,主要用於.NET框架。 2)核心概念:委託和事件允許動態綁定方法,LINQ提供強大查詢功能。 3)高級用法:異步編程提高響應性,表達式樹用於動態代碼構建。

C#.NET是構建微服務的熱門選擇,因為其生態系統強大且支持豐富。 1)使用ASP.NETCore創建RESTfulAPI,處理訂單創建和查詢。 2)利用gRPC實現微服務間的高效通信,定義和實現訂單服務。 3)通過Docker容器化微服務,簡化部署和管理。

C#和.NET的安全最佳實踐包括輸入驗證、輸出編碼、異常處理、以及身份驗證和授權。 1)使用正則表達式或內置方法驗證輸入,防止惡意數據進入系統。 2)輸出編碼防止XSS攻擊,使用HttpUtility.HtmlEncode方法。 3)異常處理避免信息洩露,記錄錯誤但不返回詳細信息給用戶。 4)使用ASP.NETIdentity和Claims-based授權保護應用免受未授權訪問。

C 語言中冒號 (':') 的含義:條件語句:分隔條件表達式和語句塊循環語句:分隔初始化、條件和增量表達式宏定義:分隔宏名和宏值單行註釋:表示從冒號到行尾的內容為註釋數組維數:指定數組的維數


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

記事本++7.3.1
好用且免費的程式碼編輯器

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

SublimeText3 Linux新版
SublimeText3 Linux最新版