C#访问远程主机资源的方法,多种方式
最近要实现访问远程主机的共享目录中的一个文件。遇到了权限问题。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);
... ...
四、角色模拟
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.IO;
namespace Test
{
public class Test
{
// 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;
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)
{
System.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;
}
public void undoImpersonation()
{
impersonationContext.Undo();
}
public void TestFunc()
{
bool isImpersonated = false;
try
{
if (impersonateValidUser("UserName", "Domain", "Password"))
{
isImpersonated = true;
//do what you want now, as the special user
// ...
File.Copy(@"\\192.168.1.48\generals\now.htm", "c:\\now.htm", true);
}
}
finally
{
if (isImpersonated)
undoImpersonation();
}
}
}
}
五、比较
方法一通过调用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#访问远程主机资源的方法,多种方式的更多相关文章
- C#访问远程主机资源的方法
实现访问远程主机的共享目录中的一个文件的解决方法: 一.调用Net use命令 // 使用方法: //if (Connect("192.168.1.48", &quo ...
- SpringMVC访问静态资源的三种方式(转)
本文转自:http://www.iigrowing.cn/springmvc_fang_wen_jing_tai_zi_yuan_de_san_zhong_fang_shi.html 如何你的Disp ...
- 转转转!SpringMVC访问静态资源的三种方式
如果你的DispatcherServlet拦截 *.do这样的URL,就不存在访问不到静态资源的问题.如果你的DispatcherServlet拦截“/”,拦截了所有的请求,同时对*.js,*.jpg ...
- 当配置 DispatcherServlet拦截“/”,SpringMVC访问静态资源的三种方式
如何你的DispatcherServlet拦截 *.do这样的URL,就不存在访问不到静态资源的问题.如果你的DispatcherServlet拦截“/”,拦截了所有的请求,同时对*.js,*.jpg ...
- 【转】SpringMVC访问静态资源的三种方式
如何你的DispatcherServlet拦截 *.do这样的URL,就不存在访问不到静态资源的问题.如果你的DispatcherServlet拦截“/”,拦截了所有的请求,同时对*.js,*.jpg ...
- SpringMVC访问静态资源的三种方式
如何你的DispatcherServlet拦截 *.do这样的URL,就不存在访问不到静态资源的问题.如果你的DispatcherServlet拦截“/”,拦截了所有的请求,同时对*.js,*.jpg ...
- springMVC访问静态资源的两种方式
1<mvc:default-servlet-handler/> 2 <mvc:resources mapping="/images/**" location=&q ...
- Spring Boot整合Servlet,Filter,Listener,访问静态资源
目录 Spring Boot整合Servlet(两种方式) 第一种方式(通过注解扫描方式完成Servlet组件的注册): 第二种方式(通过方法完成Servlet组件的注册) Springboot整合F ...
- [原创]java WEB学习笔记55:Struts2学习之路---详解struts2 中 Action,如何访问web 资源,解耦方式(使用 ActionContext,实现 XxxAware 接口),耦合方式(通过ServletActionContext,通过实现 ServletRequestAware, ServletContextAware 等接口的方式)
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
随机推荐
- MySQL管理工具MySQL Utilities — 介绍与安装(1)
MySQL Utilities介绍 MySQL Utilities 提供一组命令行工具用于维护和管理 MySQL 服务器,包括: 管理工具 (克隆.复制.比较.差异.导出.导入) 复制工具 (安装.配 ...
- LINUX下IDEA等工具调试项目时提示:Unable to open debugger port
在Ubuntu下调试项目时使用TOMCAT容器,在设置好相应的TOMCAT LOCAL 路径及相关信息后,点击调试项目出现: Unable to open debugger port : java.n ...
- Python_oldboy_自动化运维之路_面向对象2(十)
本节内容: 面向对象程序设计的由来 什么是面向对象的程序设计及为什么要有它 类和对象 继承与派生 多的态与多态性 封装 静态方法和类方法 面向对象的软件开发 反射 类的特殊成员方法 异常处理 1.面向 ...
- mybatis-config.xml 模板
ssm模板 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration ...
- [转]solver优化方法
原文地址:http://www.cnblogs.com/denny402/p/5074212.html 到目前为止,caffe总共提供了六种优化方法: Stochastic Gradient Desc ...
- sed的一些使用技巧
一.当一个文件里有两行相同的内容,但这时只想修改第一行的内容或者第二行的内容,而不是全部修改,以下例子说明下: 1.修改匹配到第一行为port的内容(若要真修改前面记得-i): [root suppo ...
- Luogu P1318 积水面积
题目描述 一组正整数,分别表示由正方体迭起的柱子的高度.若某高度值为x,表示由x个正立方的方块迭起(如下图,0<=x<=5000).找出所有可能积水的地方(图中蓝色部分),统计它们可能积水 ...
- NET-知识点:C#中Equals和==比较
第一.相等性比较 其实这个问题的的本质就是C#的相等比较,相等比较可以分两类: 1.引用相等性,引用相等性指两个对象引用均引用同一基础对象. 2.值相等性,值相等性指两个对象包含相同的一个或多个值,其 ...
- poj 1797 一条路径中的最小边 再找出最大的
Sample Input 1 // T3 3// n m1 2 3//u v w1 3 42 3 5Sample Output Scenario #1:4 # include <iostream ...
- P(查准率),R(查全率),F1 值
起源: 我们平时用的精度 accuracy,也就是整体的正确率 acc=predict_right_num/predict_num 这个虽然常用,但不能满足所有任务的需求.比如,因为香蕉太多了,也不能 ...