目录

问题案例

原因分析

解决问题

总结

问题案例

环境

电脑A:winform程序;

电脑B:部署了一个文件上传的WCF服务在IIS上。且该服务的配置文件中已经增加

<identity impersonate="true" password="" 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 命令实现路径映射,从而实现访问。

示例代码如下:

     public class FileService : IFileService
{
/// <summary>
/// FileService的静态构造函数
/// </summary>
static FileService()
{
string shareName="\\192.168.1.2\shares";
//用户名勿比指定共享服务器的IP或名称,否则会引起1312错误
string user="192.168.1.2\Test";
string pwd="";
NetUseHelper.Build(shareName, user, pwd, string.Empty);//不指定盘符,避免引起盘符被占用的错误
/*
*不建议指定盘符。因为IIS的网站默认是在IUser账户下运行的,而映射只针对'建立时的账户'有效。所以IUser下的映射又是无法预知的。
所以应该建立连接后,仍然使用共享地址访问文件或目录。
*/
} } /// <summary>
/// net use 建立映射的功能模块
/// </summary>
public static class NetUseHelper
{
/// <summary>
/// 所有支持的驱动器号
/// </summary>
static readonly string[] driveNames = { "ZYXWVUTSRQPONMLKJIHGFEDC" };
/// <summary>
/// 建立映射
/// </summary>
/// <param name="sharename">共享路径</param>
/// <param name="user">用户名。为 null 不指定用户
/// <para>请务必使用共享服务器的IP或PC名称+用户名,例如:192.168.1.1\User。否则可能引起1312错误</para>
/// </param>
/// <param name="password">密码。为 null 不指定密码</param>
/// <param name="devicename">磁盘驱动器名称,例如(C:)。为 null 自动分配驱动器号 。为 空 不指定驱动器号</param>
/// <returns>驱动器名称</returns>
public static string Build(string sharename, string user = null, string password = null, string devicename = null)
{
if (devicename != string.Empty)//为空时在已有的列表中得不到信息,所以不用判断了
{
//得到当前所有的映射驱动器及地址
var netUseList = GetAllDevic(); //标准格式
sharename = @"\\" + sharename.Trim('\\'); if (devicename == null)//自动分配驱动器号
{
for (int i = ; i < driveNames.Length; i++)
{
string name = driveNames[i];
if (netUseList.ContainsKey(name)) continue;//已存在
devicename = name;
break; }
if (devicename == null)
throw new ArgumentException("当前没有可用的驱动器号.");
}
else
{
//标准格式
devicename = devicename.Trim('\\', ':'); //判断是否已存在相同的共享
foreach (var kv in netUseList)
{
if (kv.Value == null) continue;
//驱动器号和共享路径一致
if (string.Equals(kv.Key, devicename, StringComparison.CurrentCultureIgnoreCase)
&& string.Equals(kv.Value, sharename, StringComparison.CurrentCultureIgnoreCase))
return devicename;//已存在,返回
}
//共享没在用,但其他占用驱动器号
if (netUseList.ContainsKey(devicename))
throw new ArgumentException("驱动器号" + devicename + "正在使用.");
} }
using (System.Diagnostics.Process myProcess = new System.Diagnostics.Process())
{
string command = string.Format(@"use ");
if (devicename != string.Empty)
{
command += devicename.Trim('\\', ':') + ": "; }
command += string.Format("\"{0}\" ", sharename);
if (user != null)
{
command += string.Format(@"""{0}"" /user:""{1}"" ", password, user);
}
System.IO.File.AppendAllText("d:\\log.txt", command);
//通过net use的命令 创建共享。
System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo("net ", command);
info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
info.CreateNoWindow = true;
info.UseShellExecute = false;
info.RedirectStandardError = true;
myProcess.StartInfo = info;
myProcess.Start();
myProcess.WaitForExit();
string errormsg = myProcess.StandardError.ReadToEnd(); myProcess.Close(); if (!string.IsNullOrEmpty(errormsg))
throw new InvalidOperationException(errormsg);
}
return devicename;
} /// <summary>
/// 获取当前所有的驱动器
/// <para>Key:盘符</para>
/// <para>Value:盘符ProviderName(源路径信息)。如果为本地磁盘则为null</para>
/// </summary>
/// <returns></returns>
private static Dictionary<string, string> GetAllDevic()
{
//得到当前所有的驱动器
var devicList = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
var selectQuery = new System.Management.SelectQuery("select * from win32_logicaldisk");
var searcher = new System.Management.ManagementObjectSearcher(selectQuery); foreach (System.Management.ManagementObject disk in searcher.Get())
{
var devName = disk["DeviceID"];
if (devName == null)
devName = disk["Name"];
var diskName = devName.ToString().Trim('\\', ':');
devicList.Add(diskName, null);
var access = disk["Access"];
if (access == null || access.ToString() != "") continue;//不可访问
var drivetype = disk["DriveType"];
if (drivetype == null || drivetype.ToString() != "") continue;//不是网络驱动器
var providername = disk["ProviderName"];
if (providername == null) continue;//没有映射源 devicList[diskName] = providername.ToString();
}
return devicList;
}
}

测试:多个客户端同时操作未报错。

另外,建议在对文件操作时进行异常捕捉判断,如果捕捉到FileNotFoundException 和 DirectoryNotFoundException ,说明可能发生了映射不可用的情况,应当自动建立映射。

总结

从一开始接触到这个BUG,到解决,断断续续经历了一周左右。写代码的时间也就半天不到,更多的是在查找资料、各地“求救”,很无望的赶脚。。。好了,碎碎念结束。

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

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

网站/IIS/Web/WCF服务 访问共享目录 映射 的解决方案的更多相关文章

  1. IIS发布WCF服务项目之本地

    最近由于项目需求,要做一个上传文件附件的功能,由于是多用户访问,所以这就用到了WCF服务,程序编写完成就需要发布了, 下面记录下发布到IIS的过程: 1,安装IIS 第一步:检查Windows7中II ...

  2. WCF学习笔记(2)——使用IIS承载WCF服务

    通过前面的笔记我们知道WCF服务是不能独立存在,必须“寄宿”于其他的应用程序中,承载WCF服务的应用程序我们称之为“宿主”.WCF的多种可选宿主,其中比较常见的就是承载于IIS服务中,在这里我们来学习 ...

  3. WCF技术剖析之四:基于IIS的WCF服务寄宿(Hosting)实现揭秘

    原文:WCF技术剖析之四:基于IIS的WCF服务寄宿(Hosting)实现揭秘 通过<再谈IIS与ASP.NET管道>的介绍,相信读者已经对IIS和ASP.NET的请求处理管道有了一个大致 ...

  4. iis部署wcf服务过程

    一.在iis网站中添加wcf服务,一直添加到web.config目录即可 二.点击基本设置-->连接为-->特定用户.填写登入电脑的用户名和密码. 三.点击身份验证 四.控制面板,设置防火 ...

  5. WCF开发实战系列二:使用IIS发布WCF服务

    WCF开发实战系列二:使用IIS发布WCF服务 (原创:灰灰虫的家http://hi.baidu.com/grayworm) 上一篇中,我们创建了一个简单的WCF服务,在测试的时候,我们使用VS200 ...

  6. 使用IIS承载WCF服务

    作者:jiankunking 出处:http://blog.csdn.net/jiankunking 1.WCF能够方便的通过IIS承载,此承载模型与ASP.NET和ASP.NET Web Servi ...

  7. 通过IIS寄宿WCF服务

    WCF全面解析一书中的例子S104,直接将Service目录部署到iis是无法得到服务相应的,需要在项目中新建一个web项目,删除掉自动生成的所有文件之后,把Service目录下的Calculator ...

  8. IIS 部署WCF服务注意事项

    IIS部署WCF服务的时候经常会出现如下错误: System.ServiceModel.EndpointNotFoundException”类型的未经处理的异常在 WinformWcfHost.exe ...

  9. (Tomcat)服务器之web应用的虚拟目录映射和主机搭建

    首先来了解一下web的虚拟目录映射和主机搭建的知识 第一:web的虚拟目录映射 首先我们要知道什么叫做web的虚拟目录映射,这个很好理解的,就是将我们本地硬盘上的web应用映射出一个供外界用户访问的地 ...

随机推荐

  1. osgearth cache

    <map name="readymap.org" type="geocentric"> <options> <!--Specify ...

  2. sql预计简单分页

    在显示记录条目时往往要用到分页,一种常用的办法是利用各种数据库自带的定位接口对原始查询语句进行改写,从而只取出特定范围的某些记录.不同的数据库,查询定位接口是不一样的,下面做一汇总: 数据库 分页查询 ...

  3. Win8应用开发 入门篇(三) UX交互导航模式

    导航模式(Windows 应用商店应用)   在本文中 分层模式 画布上导航 顶部应用栏 语义式缩放 相关主题 组织 Windows 应用商店应用中的内容,以便用户可以轻松而直观地进行导航.使用正确的 ...

  4. Android自定义组件——四个方向滑动的菜单实现

    今天无意中实现了一个四个方向滑动的菜单,感觉挺好玩,滑动起来很顺手,既然已经做出来了就贴出来让大家也玩弄一下. 一.效果演示 (说明:目前没有安装Android模拟器,制作的动态图片太卡了,就贴一下静 ...

  5. 【大数据系列】使用api修改hadoop的副本数和块大小

    package com.slp.hdfs; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.h ...

  6. jQuery Sizzle选择器(三)

    在Sizzle的入口方法Sizzle()中看到的一个根据浏览器来初始化document各个方法的函数setDocument(),接下来主要看一下这个方法都做了什么. 但之前有必要看一下它用到的一些Si ...

  7. google v8引擎常见问题

    最近在项目中使用v8来进行扩展,下面简单说一下使用v8过程中遇到的一些问题.   v8的多线程调用 最初调研v8的测试代码是单线程的,后来一个项目在多线程中使用,出现了一些问题,后来看到参考3中的才恍 ...

  8. filter对数组和对象的过滤

    1,对数组的过滤 let arr = ['1', '2', '3'] let b = arr.filter(val => val === '2') console.log(b) // ['2] ...

  9. 遍历json数组实现树

    今天小颖在工作中遇到要遍历树得问题了,实现后,怕后期遇到又忘记啦,所以记录下嘻嘻,其实这个和小颖之前写过得一篇文章    json的那些事    中第4点有关json的面试题有些类似. 数组格式: v ...

  10. hdu3507 Print Article[斜率优化dp入门题]

    Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)To ...