zoukankan      html  css  js  c++  java
  • 网站/IIS/Web/WCF服务 访问共享目录 映射 的解决方案

    目录

    问题案例

    原因分析

    解决问题

    总结

    问题案例

    环境

    电脑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.2shares";
      9             //用户名勿比指定共享服务器的IP或名称,否则会引起1312错误
     10             string user="192.168.1.2Test";
     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.1User。否则可能引起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[i];
     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,到解决,断断续续经历了一周左右。写代码的时间也就半天不到,更多的是在查找资料、各地“求救”,很无望的赶脚。。。好了,碎碎念结束。

    其实仔细想想,冷静下来,才会有更多的思路。

    最后,如果各位有更好的方式?还望示下。

  • 相关阅读:
    git 项目代码打包
    jira查看字段
    jmeter压力测试报错:java.net.BindException: Address already in use: connect解决办法
    python 破解验证码
    mysql授权远程登录
    豆瓣api
    利用python开发财务工具
    钉钉发送消息通知
    git使用命令行自动登录
    后宫
  • 原文地址:https://www.cnblogs.com/xiaotiannet/p/4031965.html
Copyright © 2011-2022 走看看