一顿饭的缘分 發表於 2025-6-16 11:41:00

(原创)[C#]一步步解决DotNetZip因超长路径(MAX_PATH)报错的问题。

<h1 id="一前言">一、前言</h1>
<p>超长路径(MAX_PATH)的问题,在很多地方都可能遇到,常见的解决办法无非三种:添加前缀\\?\、app.config添加配置、修改注册表等。</p>
<p>而对于其它第三方的DLL,我们如何去从外部解决呢?答案是:反射。</p>
<p>本篇文章,我们就以DotNetZip为例,一步步来解决超长路径的问题。</p>
<p>**相信看完的你,一定会有所收获!<br>
**<br>
本文地址:https://www.cnblogs.com/lesliexin/p/18930533</p>
<h1 id="二一步步定位问题">二、一步步定位问题</h1>
<p>首先,我们看下使用DotNetZip的ZipEntry.AddDictionary()方法添加一个目录后,相关属性的变化。</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250616105911644-1321561690.png" alt="image" loading="lazy"></p>
<p>我们可以看到,在添加前,ZipFile.Entries是空的。</p>
<p>在添加后,变化如下:</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250616110103666-1926851721.png" alt="image" loading="lazy"></p>
<p>会遇到超长路径(MAX_PATH)报错,肯定会有一个完整的路径,当然存在临时拼接的情况,但是我们先找一找。</p>
<p>最后,我们在“非公开成员”中找到一个属性:LocalFileName,其值正是完整的文件路径,如下图所示:</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250616110321369-1372529587.png" alt="image" loading="lazy"></p>
<p>为了方便观察,我们将LocalFileName属性置顶显示:</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250616110433173-20664567.png" alt="image" loading="lazy"></p>
<p>之后我们就可以看到,默认显示的都是LocalFileName了:</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250616110540820-245391064.png" alt="image" loading="lazy"></p>
<p>现在我们找到这个关键的LocalFileName,虽然还不能百分百确定和这有关,但是可以以此为准进行后面的排查和验证了。</p>
<h1 id="三反编译梳理逻辑">三、反编译梳理逻辑</h1>
<p>像DotNetZip,是开源的,我们可以直接找到源码来查看,对于非开源的,我们就只能反编译了。</p>
<p>这里常用的工具是dnSpy,我们使用dnSpy打开DotNetZip,然后定位到ZipEntry,再找到LocalFileName属性:</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250616111847118-886133093.png" alt="image" loading="lazy"></p>
<p>可以看到只有get,没有set,这样的话,如果直接反射操作此属性,则需要额外的添加set访问器,非常麻烦,此时不作考虑。</p>
<p>我们再看,LocalFileName其实是返回的变量:_LocalFileName,我们再找下此变量:</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250616112048985-1152562369.png" alt="image" loading="lazy"></p>
<p>这样的话就简单了,我们反射直接操作此变量:</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250616112200368-188527829.png" alt="image" loading="lazy"></p>
<p>我们在处理时,先进行判断是否超长,再反射处理,因为反射是很耗资源的。</p>
<p>至于扩展方法,定义如下:</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250616112223118-1256198166.png" alt="image" loading="lazy"></p>
<p>说一下这里面为什么要以248作为判断条件,是因为260是文件路径限制,而对于目录则是以248为限制,所以我们以最小的为主进行判断。</p>
<h1 id="四验证">四、验证</h1>
<p>这里就不贴图了,验证发现已经可以正常处理超长路径了,不会再报错了。</p>
<blockquote>
<p>在解决此问题时,其实也是会捋一下相关的代码逻辑的,看看是不是真的只处理此变量就行了,只是本次这个很确定,再捋代码流程也没必要,也不是本文的重点,就不再赘述了。</p>
</blockquote>
<h1 id="五开源">五、开源</h1>
<p>因为DotNetZip已经不再积极维护,且Nuget上的版本也标记了弃用和风险,所以也就不提PR了,</p>
<p>但在这么多压缩解压缩库中,DotNetZip在易用性上是无与伦比的,所以在很多时候用用还是挺不错的。也基于此想法,正好也将自己之前封装的方法给开源了吧,基于DotNetZip,就两个方法:Zip、UnZip。简单易用、解决了超长路径(MAX_PATH)问题、支持密码、分卷。</p>
<p>开源地址:https://gitee.com/lesliexin/lesliexin.simplezip</p>
<p>NuGet:https://www.nuget.org/packages/LeslieXin.SimpleZip</p>
<h1 id="六结语">六、结语</h1>
<p>这次也是遇到了这个超长路径(MAX_PATH)的问题,才想起来修复下,顺便也开源下自己的库。</p>
<p>本篇文章最重要的是给读者一个遇到超长路径(MAX_PATH)问题时一个实操指导,毕竟此问题不止会发生在DotNetZip中,可能发生在任何与文件路径相关的地方,当再次遇到此问题时,该如何一步步去排查定位和处理。</p>
<p>感谢大家的观看,本人水平有限,文章不足之处欢迎大家评论指正。</p>
<p>--</p><br><br>
来源:https://www.cnblogs.com/lesliexin/p/18930533
頁: [1]
查看完整版本: (原创)[C#]一步步解决DotNetZip因超长路径(MAX_PATH)报错的问题。