一、背景
      当windows系统下使用System.IO命名空间下的方法,目录长度超过260个字符时,.net framework会抛出LongPathException。查阅相关资料,发现是微软为了安全和系统兼容性做出的限制。
      原话是这么说的:The exception that is thrown when a path or file name is longer than the system-defined maximum length.
      关于这个问题更详细的说明在这里:http://blogs.msdn.com/b/bclteam/archive/2007/02/13/long-paths-in-net-part-1-of-3-kim-hamilton.aspx
      当然有过人已经中文翻译过来了: http://www.cnblogs.com/tongling/archive/2007/04/26/728224.html

LongPathException详细:http://msdn.microsoft.com/en-us/library/System.IO.PathTooLongException(v=vs.110).aspx

二、解决方案

方法一:用官方说的方法,用unicode的编码方式调用win32 API,并且在路径前面加前缀:\\?\。

这个链接是官方提供的解决办法: http://msdn.microsoft.com/en-us/library/930f87yf(vs.80).aspx
下面是包装了CreateDirectory和CreateFile。经过测试,可以正常使用。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
using System.IO; namespace STAr.Aquarius.Infrastructure.Library
{
public static class LongPathHelper
{
static class Win32Native
{
[StructLayout(LayoutKind.Sequential)]
public class SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr pSecurityDescriptor;
public int bInheritHandle;
} [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CreateDirectory(string lpPathName, SECURITY_ATTRIBUTES lpSecurityAttributes); [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess, FileShare dwShareMode, SECURITY_ATTRIBUTES securityAttrs, FileMode dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile);
} public static bool CreateDirectory(string path)
{
return Win32Native.CreateDirectory(String.Concat(@"\\?\", path), null);
}
public static SafeFileHandle CreateFile(string path)
{
SafeFileHandle handle = Win32Native.CreateFile(String.Concat(@"\\?\", path), (int)0x10000000, FileShare.None, null, FileMode.CreateNew, (int)0x00000080, IntPtr.Zero);
if (handle.IsInvalid)
{
throw new System.ComponentModel.Win32Exception();
}
return handle;
}
public static FileStream Open(string path, FileMode mode, FileAccess access)
{
SafeFileHandle handle = Win32Native.CreateFile(String.Concat(@"\\?\", path), (int)0x10000000, FileShare.None, null, mode, (int)0x00000080, IntPtr.Zero);
if (handle.IsInvalid)
{
throw new System.ComponentModel.Win32Exception();
}
return new FileStream(handle, access);
} }
}

其他使用到的API,自己在按照上面的方法包装即可。这种方法可以解决问题,就是太麻烦,因为所有用到的都需要自己动手包装,费力不讨好不说,PInvoke的调用写起来也比较麻烦,不知道大家有没有一种好的办法,可以高效的解决这个问题。
我只知道有一个pinvoke.net的网站上可以查询相关API的写法。有更好的方法,记得告诉我哦。

方法二、用第三方开源类库:alphafs
官方地址:http://alphafs.codeplex.com/
这个alphafs是对System.IO.FileStream的完整包装,几乎支持所有的System.IO.File,System.IO.Directory.System.IO.FileStream...

原话:AlphaFS is a .NET library providing more complete Win32 file system functionality to the .NET platform than the standard System.IO classes. 
,还有一个好处是,他的方法名和System.IO完全一样。那我们改起来只需要修改引用不就可以了吗。
下面写的测试程序,经测,可以使用:(ps需要引用AlphaFS.dll这个dll.)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Alphaleonis.Win32.Filesystem; namespace LongPath
{
/// <summary>
/// http://stackoverflow.com/questions/12747132/pathtoolongexception-c-sharp-4-5
/// http://msdn.microsoft.com/en-us/library/930f87yf(vs.80).aspx
/// https://zetalongpaths.codeplex.com/
/// http://alphafs.codeplex.com/
/// Author:http://www.cnblogs.com/deepleo/
/// Email:2586662969@qq.com
/// </summary>
class Program
{
static void Main(string[] args)
{
var path = @"\\?\C:\Issues\20140710\20140710\20140710\20140710\20140710\20140710\20140710\20140710\20140710\20140710\20140710\20140710\20140710\ProblemOvernight\Data\[20140812_162155_][20140812_162155][20140812_162155][20140812_162155]\[20140812_162155_][20140812_162155][20140812_162155][20140812_162155]";
if (!Directory.Exists(path)) Directory.CreateDirectory(path);
Console.WriteLine("Path's Length is {0}", path.Length);
var newDir = string.Concat(path, @"\" + Guid.NewGuid().ToString());
Directory.CreateDirectory(newDir);
Console.WriteLine("New dir is created {0}", Directory.Exists(newDir));
var newFile = Path.Combine(newDir, Guid.NewGuid().ToString());
File.Create(newFile);
Console.WriteLine("New file is created {0}", File.Exists(newFile));
Console.ReadKey();
}
}
}

当然,最好的解决办法是,你能说服你的客户,不改,让他不要把路径搞那么长,算你牛逼!!!

下面附上完整测试程序源代码:http://files.cnblogs.com/deepleo/LongPath.rar

alphafs可以到官方网站上下载,也可以在我这里下载:http://files.cnblogs.com/deepleo/AlphaFS.rar

LongPathException问题解析的更多相关文章

  1. 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新

    本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...

  2. .NET Core中的认证管理解析

    .NET Core中的认证管理解析 0x00 问题来源 在新建.NET Core的Web项目时选择“使用个人用户账户”就可以创建一个带有用户和权限管理的项目,已经准备好了用户注册.登录等很多页面,也可 ...

  3. Html Agility Pack 解析Html

    Hello 好久不见 哈哈,今天给大家分享一个解析Html的类库 Html Agility Pack.这个适用于想获取某网页里面的部分内容.今天就拿我的Csdn的博客列表来举例. 打开页面  用Fir ...

  4. 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新

    [原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...

  5. 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新

    上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...

  6. 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例

    前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...

  7. Asp.Net WebApi核心对象解析(下篇)

    在接着写Asp.Net WebApi核心对象解析(下篇)之前,还是一如既往的扯扯淡,元旦刚过,整个人还是处于晕的状态,一大早就来处理系统BUG,简直是坑爹(好在没让我元旦赶过来该BUG),队友挖的坑, ...

  8. 【知识必备】内存泄漏全解析,从此拒绝ANR,让OOM远离你的身边,跟内存泄漏say byebye

    一.写在前面 对于C++来说,内存泄漏就是new出来的对象没有delete,俗称野指针:而对于java来说,就是new出来的Object放在Heap上无法被GC回收:而这里就把我之前的一篇内存泄漏的总 ...

  9. SQL Server 数据加密功能解析

    SQL Server 数据加密功能解析 转载自: 腾云阁 https://www.qcloud.com/community/article/194 数据加密是数据库被破解.物理介质被盗.备份被窃取的最 ...

随机推荐

  1. jsp分页完善版

    明天要考网络工程师了,而且这两天校运会,把那个分页的完善了下,明天考试,祈祷吧,我根本都没看书啊,所以只能去长见识了.100大洋啊,下个学期我想考考证了,不然以后出去麻烦了.呵呵,不多说还是说说自己对 ...

  2. swift c++ oc 混编

    http://www.tuicool.com/articles/QZNrErM iOS 里面 Swift与Objective-C混编,Swift与C++混编的一些比较 时间 2015-03-23 23 ...

  3. DDD——让天下没有难调的程序

    https://www.linuxidc.com/Linux/2016-11/137343.htm DDD全称Data Display Debugger,当我第一次见到它时,它的界面着实让我吃了一惊, ...

  4. 本地搭建SVN局域网服务器【转】

    转自:http://blog.csdn.net/sunbaigui/article/details/8466310 参考链接:http://tortoisesvn.net/docs/nightly/T ...

  5. IC卡的传输协议(2)-块传输协议T=1【转】

    转自:http://bbs.ednchina.com/BLOG_ARTICLE_172024.HTM 2.4 块传输协议T=1 T=1协议中,在TAL和IC卡之间传送的命令.R-APDU和传输控制信息 ...

  6. linux 中解析命令行参数(getopt_long用法)

    linux 中解析命令行参数(getopt_long用法) http://www.educity.cn/linux/518242.html 详细解析命令行的getopt_long()函数 http:/ ...

  7. Charles Android 抓包失败SSLHandshake: Received fatal alert: certificate_unknown

    前提: Android使用Charles抓取Https请求的报文时,Android和Charles都正确安装了证书之后出现抓包失败,报错SSLHandshake: Received fatal ale ...

  8. mysql绿色版配置

    MySQL 绿色版安装配置教程 一.下载,这里使用绿色免安装版 1.网上搜索mysql绿色免安装版下载即可.提供官网地址 http://dev.mysql.com/downloads/mysql--- ...

  9. k8s通过configmap管理应用配置信息

    Secret 可以为 Pod 提供密码.Token.私钥等敏感数据:对于一些非敏感数据,比如应用的配置信息,则可以用 ConfigMap. ConfigMap 的创建和使用方式与 Secret 非常类 ...

  10. k8s创建资源的两种方式

    命令 vs 配置文件 Kubernetes 支持两种方式创建资源: 1. 用 kubectl 命令直接创建 kubectl run nginx-deployment --image=nginx: -- ...