设为首页 收藏本站
查看: 2054|回复: 0

[经验分享] 网站/IIS/Web/WCF服务 访问共享目录 映射 的解决方案

[复制链接]
发表于 2015-8-13 10:52:38 | 显示全部楼层 |阅读模式
目录
  问题案例
  原因分析
  解决问题
  总结

问题案例
  环境
  电脑A:winform程序;
  电脑B:部署了一个文件上传的WCF服务在IIS上。且该服务的配置文件中已经增加



<identity impersonate="true" password="1234" userName="Test" />
//该账户同时存在于电脑B和电脑C中
  ;
  电脑C:公布的共享路径;
  在A的winform程序连接B的WCF服务上传文件,B的WCF服务将文件保存至C的共享路径中。
  结果:路径无法访问。



System.UnauthorizedAccessException: 对路径“”的访问被拒绝
  对比:同样的操作使用wevservice和.aspx都可以正常访问共享路径并操作。
  期望/最终目的:找到可以在WCF中访问共享路径的解决方案。
  

原因分析
  排除:权限不足的原因
  因为其他两种方式(WebService和.aspx)在没有配置【Asp.net模拟】的身份验证方式之前,也是同样的错误。使用【Asp.net模拟】的身份验证后,就可以正常操作。
  所以我在想是不是因为WCF未能调用【Asp.net模拟】的身份验证?或者说该项配置对WCF无效?
  
  ================2014-10-20==============
  排除:服务引用方式
  尝试使用 Web References 的方式添加WCF服务的引用(之前是Service References )。问题依旧。
  

解决问题
  
  方案:在WCF服务的静态构造函数中,通过调用net use 命令实现路径映射,从而实现访问。
  示例代码如下:  



  1     public class FileService : IFileService
  2     {
  3         /// <summary>
  4         /// FileService的静态构造函数
  5         /// </summary>
  6         static FileService()
  7         {
  8             string shareName="\\192.168.1.2\shares";
  9             //用户名勿比指定共享服务器的IP或名称,否则会引起1312错误
10             string user="192.168.1.2\Test";
11             string pwd="123";
12             NetUseHelper.Build(shareName, user, pwd, string.Empty);//不指定盘符,避免引起盘符被占用的错误
13             /*        
14                          *不建议指定盘符。因为IIS的网站默认是在IUser账户下运行的,而映射只针对'建立时的账户'有效。所以IUser下的映射又是无法预知的。
15                           所以应该建立连接后,仍然使用共享地址访问文件或目录。
16              */
17         }
18
19     }
20
21     /// <summary>
22     /// net use 建立映射的功能模块
23     /// </summary>
24     public static class NetUseHelper
25     {
26         /// <summary>
27         /// 所有支持的驱动器号
28         /// </summary>
29         static readonly string[] driveNames = { "ZYXWVUTSRQPONMLKJIHGFEDC" };
30         /// <summary>
31         /// 建立映射
32         /// </summary>
33         /// <param name="sharename">共享路径</param>
34         /// <param name="user">用户名。为 null 不指定用户
35         /// <para>请务必使用共享服务器的IP或PC名称+用户名,例如:192.168.1.1\User。否则可能引起1312错误</para>
36         /// </param>
37         /// <param name="password">密码。为 null 不指定密码</param>
38         /// <param name="devicename">磁盘驱动器名称,例如(C:)。为 null 自动分配驱动器号 。为 空 不指定驱动器号</param>
39         /// <returns>驱动器名称</returns>
40         public static string Build(string sharename, string user = null, string password = null, string devicename = null)
41         {
42             if (devicename != string.Empty)//为空时在已有的列表中得不到信息,所以不用判断了
43             {
44                 //得到当前所有的映射驱动器及地址
45                 var netUseList = GetAllDevic();
46
47                 //标准格式
48                 sharename = @"\\" + sharename.Trim('\\');
49
50                 if (devicename == null)//自动分配驱动器号
51                 {
52                     for (int i = 0; i < driveNames.Length; i++)
53                     {
54                         string name = driveNames;
55                         if (netUseList.ContainsKey(name)) continue;//已存在
56                         devicename = name;
57                         break;
58
59                     }
60                     if (devicename == null)
61                         throw new ArgumentException("当前没有可用的驱动器号.");
62                 }
63                 else
64                 {
65                     //标准格式
66                     devicename = devicename.Trim('\\', ':');
67
68                     //判断是否已存在相同的共享
69                     foreach (var kv in netUseList)
70                     {
71                         if (kv.Value == null) continue;
72                         //驱动器号和共享路径一致
73                         if (string.Equals(kv.Key, devicename, StringComparison.CurrentCultureIgnoreCase)
74                             && string.Equals(kv.Value, sharename, StringComparison.CurrentCultureIgnoreCase))
75                             return devicename;//已存在,返回
76                     }
77                     //共享没在用,但其他占用驱动器号
78                     if (netUseList.ContainsKey(devicename))
79                         throw new ArgumentException("驱动器号" + devicename + "正在使用.");
80                 }
81
82             }
83             using (System.Diagnostics.Process myProcess = new System.Diagnostics.Process())
84             {
85                 string command = string.Format(@"use ");
86                 if (devicename != string.Empty)
87                 {
88                     command += devicename.Trim('\\', ':') + ": ";
89
90                 }
91                 command += string.Format("\"{0}\" ", sharename);
92                 if (user != null)
93                 {
94                     command += string.Format(@"""{0}"" /user:""{1}"" ", password, user);
95                 }
96                 System.IO.File.AppendAllText("d:\\log.txt", command);
97                 //通过net use的命令 创建共享。
98                 System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo("net ", command);
99                 info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
100                 info.CreateNoWindow = true;
101                 info.UseShellExecute = false;
102                 info.RedirectStandardError = true;
103                 myProcess.StartInfo = info;
104                 myProcess.Start();
105                 myProcess.WaitForExit(6000);
106                 string errormsg = myProcess.StandardError.ReadToEnd();
107
108                 myProcess.Close();
109
110                 if (!string.IsNullOrEmpty(errormsg))
111                     throw new InvalidOperationException(errormsg);
112             }
113             return devicename;
114         }
115
116         /// <summary>
117         /// 获取当前所有的驱动器
118         /// <para>Key:盘符</para>
119         /// <para>Value:盘符ProviderName(源路径信息)。如果为本地磁盘则为null</para>
120         /// </summary>
121         /// <returns></returns>
122         private static Dictionary<string, string> GetAllDevic()
123         {
124             //得到当前所有的驱动器
125             var devicList = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
126             var selectQuery = new System.Management.SelectQuery("select * from win32_logicaldisk");
127             var searcher = new System.Management.ManagementObjectSearcher(selectQuery);
128
129             foreach (System.Management.ManagementObject disk in searcher.Get())
130             {
131                 var devName = disk["DeviceID"];
132                 if (devName == null)
133                     devName = disk["Name"];
134                 var diskName = devName.ToString().Trim('\\', ':');
135                 devicList.Add(diskName, null);
136                 var access = disk["Access"];
137                 if (access == null || access.ToString() != "0") continue;//不可访问
138                 var drivetype = disk["DriveType"];
139                 if (drivetype == null || drivetype.ToString() != "4") continue;//不是网络驱动器
140                 var providername = disk["ProviderName"];
141                 if (providername == null) continue;//没有映射源
142
143                 devicList[diskName] = providername.ToString();
144             }
145             return devicList;
146         }
147     }
  
  测试:多个客户端同时操作未报错。
  另外,建议在对文件操作时进行异常捕捉判断,如果捕捉到FileNotFoundException 和 DirectoryNotFoundException ,说明可能发生了映射不可用的情况,应当自动建立映射。
  

总结
  从一开始接触到这个BUG,到解决,断断续续经历了一周左右。写代码的时间也就半天不到,更多的是在查找资料、各地“求救”,很无望的赶脚。。。好了,碎碎念结束。
  其实仔细想想,冷静下来,才会有更多的思路。
  最后,如果各位有更好的方式?还望示下。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-98387-1-1.html 上篇帖子: 十步!轻松搞定IIS+PHP环境 下篇帖子: 关于IIS、Jexus、Node.js、OpenResty的简单测试
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表