溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

C#訪問(wèn)遠(yuǎn)程主機(jī)資源的方法有哪些

發(fā)布時(shí)間:2021-03-10 10:21:42 來(lái)源:億速云 閱讀:272 作者:小新 欄目:編程語(yǔ)言

這篇文章主要介紹了C#訪問(wèn)遠(yuǎn)程主機(jī)資源的方法有哪些,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。


一、調(diào)用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;
        }

二、調(diào)用WNetAddConnection2、WNetAddConnection3或者NetUseAdd函數(shù),進(jìn)行磁盤映射。

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的格式一定要正確,否則可能出現(xiàn)錯(cuò)誤            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類來(lái)傳輸文件。
添加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)            {                // 如果網(wǎng)絡(luò)很慢,而文件又很大,這時(shí)可能有超時(shí)異常(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)            {                // 如果網(wǎng)絡(luò)很慢,而文件又很大,這時(shí)可能有超時(shí)異常(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>
    /// 身份模擬實(shí)現(xiàn)遠(yuǎn)程資源訪問(wèn)
    /// </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">獨(dú)立服務(wù)器用IP,域環(huán)境就用域名</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來(lái)訪問(wèn)遠(yuǎn)程資源。
                // 如果要(通過(guò)模擬用戶獲得權(quán)限)實(shí)現(xiàn)服務(wù)器程序,訪問(wèn)本地授權(quán)數(shù)據(jù)庫(kù)可
                // 以用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">獨(dú)立服務(wù)器用IP,域環(huán)境就用域名</param>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <param name="act">需要執(zhí)行的操作</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);
                }
            });

五、比較

方法一通過(guò)調(diào)用Shell命令Net Use實(shí)現(xiàn),有點(diǎn)笨拙。
方法二和方法一有些相似之處。映射遠(yuǎn)程資源,然后訪問(wèn)。
方法三由于會(huì)有超時(shí)異常出現(xiàn),所以在網(wǎng)絡(luò)速度快、傳輸小文件時(shí)是可以的。
方法四通過(guò)身份模擬實(shí)現(xiàn)遠(yuǎn)程資源訪問(wèn)。一些服務(wù)器進(jìn)程就是通過(guò)這種方式運(yùn)行的。這種方法也是我的最愛。

六、要注意的地方

關(guān)于這幾種方法,google后都可以找到一些文章。但是等到自己實(shí)際測(cè)試時(shí),有時(shí)會(huì)出現(xiàn)各種小錯(cuò)誤,
這些錯(cuò)誤基本來(lái)源于兩方面:

1、函數(shù)的參數(shù)選擇有問(wèn)題,和自己的環(huán)境不相符。
比如        

public static extern int LogonUser(String lpszUserName,
            String lpszDomain,
            String lpszPassword,
            int dwLogonType,
            int dwLogonProvider,
            ref IntPtr phToken);

中的dwLogonType,要訪問(wèn)遠(yuǎn)程資源就要用LOGON32_LOGON_NEW_CREDENTIALS,
要模擬本機(jī)用戶就要用LOGON32_LOGON_INTERACTIVE。

2、函數(shù)的參數(shù)格式有問(wèn)題。
   a、比如

 public static extern int LogonUser(String lpszUserName,
            String lpszDomain,
            String lpszPassword,
            int dwLogonType,
            int dwLogonProvider,
            ref IntPtr phToken);

中的lpszUserName、lpszDomain、lpszPassword就要寫清楚。

   我就在這遇到過(guò)問(wèn)題,第一次測(cè)試時(shí),遠(yuǎn)程服務(wù)器就是一臺(tái)獨(dú)立的文件服務(wù)器,這是我的調(diào)用方式:
       LogonUser("myname", "192.168.1.48", "password", LOGON32_LOGON_NEW_CREDENTIALS,
                   LOGON32_PROVIDER_DEFAULT, ref token);

   第二次測(cè)試時(shí),遠(yuǎn)程服務(wù)器是域MyDomain中的一個(gè)成員服務(wù)器,提供文件服務(wù)。這時(shí)代碼就應(yīng)該是:

 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\”就會(huì)出錯(cuò);
   如果是域中的用戶,那么把@"Domain\UserName"變成@"UserName"就會(huì)出錯(cuò)。

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“C#訪問(wèn)遠(yuǎn)程主機(jī)資源的方法有哪些”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI