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,到解决,断断续续经历了一周左右。写代码的时间也就半天不到,更多的是在查找资料、各地“求救”,很无望的赶脚。。。好了,碎碎念结束。

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

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

  • 相关阅读:
    jvisualm 结合 visualGC 进行jvm监控,并分析垃圾回收
    linux 查看服务器cpu 与内存配置
    arthas 使用总结
    selinux contexts 安全上下文的临时更改
    Android 8.1 Doze模式分析(五) Doze白名单及Debug方式
    Window 任意窗口置顶软件Window TopMost Control
    Android ApkToolPlus一个可视化的跨平台 apk 分析工具
    SVN Please execute the 'Cleanup' command.
    Android 如何在64位安卓系统中使用32位SO库
    Android cmd命令查看apk是32位还是64位?
  • 原文地址:https://www.cnblogs.com/xiaotiannet/p/4031965.html
Copyright © 2011-2022 走看看