目录.EnumerateFiles =>未经授权的访问异常
.NET 4.0 中有一个很好的新方法,可以通过枚举以流方式获取目录中的文件。
这里的问题是,如果希望枚举所有文件,则可能无法提前知道哪些文件或文件夹受到访问保护,并且可能会抛出 UnauthorizedAccessException。
要重现,只需运行此片段:
foreach (var file in Directory.EnumerateFiles(@"c:\", "*", SearchOption.AllDirectories))
{
// whatever
}
在此 .NET 方法存在之前,可以通过在字符串数组返回方法上实现递归迭代器来实现大致相同的效果。但它并不像新的 .NET 方法那么懒惰。
那么该怎么办呢?使用此方法时,UnauthorizedAccessException 是否可以被抑制或者是不可避免的事实?
在我看来,该方法应该有一个重载,接受一个操作来处理任何异常。
There is a nice new method in .NET 4.0 for getting files in a directory in a streaming way via enumeration.
The problem here is that if one wishes to enumerate all files one may not know in advance which files or folders are access protected and can throw an UnauthorizedAccessException.
To reproduce, one can just run this fragment:
foreach (var file in Directory.EnumerateFiles(@"c:\", "*", SearchOption.AllDirectories))
{
// whatever
}
Before this .NET method existed it was possible to achieve roughly the same effect by implementing a recursive iterator on the string-array returning methods. But it's not quite as lazy as the new .NET method is.
So what to do? Can the UnauthorizedAccessException be suppressed or is a fact of life when using this method?
Seems to me that the method should have an overload accepting an action to deal with any exceptions.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我无法使上述工作正常,但这是我的实现,我已经在“Win7”盒子上的 c:\users 上测试了它,因为如果有所有这些“讨厌的”目录:
类:
I Couldn't get the above to work, but here is my implementation, i've tested it on c:\users on a "Win7" box, because if has all these "nasty" dirs:
Class:
上述答案的问题是它不处理子目录中的异常。这将是处理这些异常的更好方法,因此您可以从所有子目录中获取所有文件,除了那些抛出访问异常的文件:
Ths issue with the above answer is that is does not take care of exception in sub directories. This would be a better way to handling those exceptions so you get ALL files from ALL subdirectories except those with threw an access exception:
我知道是
MoveNext
引发了异常。我尝试编写一个方法来安全地遍历序列并尝试忽略
MoveNext
异常。但是我不确定MoveNext
在抛出异常时是否会前进位置,所以这也可能是无限循环。这也是一个坏主意,因为我们将依赖于实现细节。但这只是太有趣了!
只有当框架实现此迭代器时满足以下条件时,这才会起作用(请参阅 Reflector 中的
FileSystemEnumerableIterator
以供参考):MoveNext
在最后一个元素上失败时,后续调用将返回false
而不是抛出异常;即使它有效,也请不要在生产中使用它!
但我真的想知道是否真的如此。
I understand it's
MoveNext
that throws the exception.I tried to write a method that safe-walks a sequence and tries to ignore
MoveNext
exceptions. However I'm not sure ifMoveNext
advances position when it throws an exception, so this might as well be infinite loop. It is also bad idea because we would rely on implementation details.But it's just so much fun!
This will only work if the following conditions are true about framework's implementation of this iterator (see
FileSystemEnumerableIterator<TSource>
in Reflector for reference):MoveNext
advances its position when it fails;MoveNext
fails on last element, subsequent calls will returnfalse
instead of throwing an exception;Even if it works, please, never use it in production!
But I really wonder if it does.
作为答案发布,因为我没有代表添加评论,更不用说编辑现有答案了。我的要求是尽量减少内存分配、冗余变量,并让系统对目录进行一次枚举。
丹·贝查德 (Dan Bechard) 在评论中提到:
这可能已在较新版本的 .Net 或 Windows 10 版本中修复?我在 Windows 10 上的 .NET 5.0 中没有遇到此问题。通过搜索整个系统驱动器进行测试。
在 VB.NET 中:
Posting as an answer since I don't have the rep to add a comment let alone edit existing answers. My requirement was to minimize memory allocations, redundant variables, and have the system do a single enumeration of the directory.
Dan Bechard mentions in a comment:
This may have been fixed in either a newer release of .Net or in a Windows 10 build? I'm not having this issue in .NET 5.0 on Windows 10. Tested by searching my entire system drive.
In VB.NET:
我迟到了,但我建议改用可观察模式:
I'm late, but I suggest using observable pattern instead:
我自己做了一个围绕这个问题的类的实现,因为以前的答案似乎没有做我想做的事。这只是跳过它无法访问的所有文件和文件夹,并返回它可以访问的所有文件。
与常规 EnumerateFiles 函数完全相同,只需使用 SafeWalk.EnumerateFiles(...) 而不是 Dictionary.EnumerateFiles(...)
I made my own Implementation of a Class that works arround this, as previous answers didnt seem to do what i wanted to. This simply skips all Files and Folders that it can not access, and returns all files that it could access.
Usable exactly like the regular EnumerateFiles function, simply using SafeWalk.EnumerateFiles(...) instead of Dictionary.EnumerateFiles(...)