C# 忽略Directory.Enumerate文件的异常,跳过这些文件
在枚举时,我想跳过/忽略异常 我尝试在选择器中添加一个try catch:C# 忽略Directory.Enumerate文件的异常,跳过这些文件,c#,C#,在枚举时,我想跳过/忽略异常 我尝试在选择器中添加一个try catch: static IEnumerable<string> GetSafeAllFiles (string path, string searchPattern, SearchOption searchOption = SearchOption.AllDirectories) { return Directory.EnumerateFiles(path, searchPattern, searchO
static IEnumerable<string> GetSafeAllFiles
(string path, string searchPattern, SearchOption searchOption = SearchOption.AllDirectories)
{
return Directory.EnumerateFiles(path, searchPattern, searchOption)
.Select(f =>
{
try
{
return f;
}
catch (Exception e)
{
return string.Empty;
}
});
}
没有结果,因为它将在第一个错误后停止。因此,我尝试实施我自己的:
static IEnumerable<string> test12(string path, string searchPattern, SearchOption searchOption = SearchOption.AllDirectories)
{
if (string.IsNullOrEmpty(path))
{
throw new ArgumentNullException("path");
}
if (string.IsNullOrEmpty(searchPattern))
{
throw new ArgumentNullException("searchPattern");
}
Queue<string> stillToProcess = new Queue<string>(new[] { path });
foreach (var dir in Directory.EnumerateDirectories(path))
{
stillToProcess.Enqueue(dir);
}
while (stillToProcess.Count > 0)
{
string currentPath = stillToProcess.Dequeue();
IEnumerable<string> ret = Enumerable.Empty<string>();
try
{
ret = Directory.EnumerateFiles(currentPath, searchPattern);
}
catch (UnauthorizedAccessException e)
{ }
// yield! keyword
foreach (var i in ret) { yield return i; }
}
yield break;
}
static IEnumerable test12(字符串路径、字符串搜索模式、SearchOption SearchOption=SearchOption.AllDirectories)
{
if(string.IsNullOrEmpty(path))
{
抛出新的ArgumentNullException(“路径”);
}
if(string.IsNullOrEmpty(searchPattern))
{
抛出新的ArgumentNullException(“searchPattern”);
}
Queue stillToProcess=新队列(new[]{path});
foreach(目录中的var dir.EnumerateDirectories(path))
{
stillToProcess.Enqueue(dir);
}
while(stillToProcess.Count>0)
{
字符串currentPath=stillToProcess.Dequeue();
IEnumerable ret=Enumerable.Empty();
尝试
{
ret=目录.枚举文件(currentPath,searchPattern);
}
捕获(未经授权的访问例外)
{ }
//屈服!关键字
foreach(var i in ret){收益率i;}
}
屈服断裂;
}
但如果有一个错误,它会跳过目录。当我只想跳过错误文件时
为了测试,可能的解决方案请在
c:\$Recycle.Bin
上执行,因为它是未经授权的访问异常的最简单来源。几天前,我编写了这段代码,以获取目录和所有子目录中的所有文件。我会走这条路来实现你的目标。您必须自定义它以使用搜索模式和搜索选项。否则,CanRead方法可以通过防止代码整体抛出异常来解决您的问题
public class DirectoryAnalyser
{
private List<string> _files;
private int _directoryCounter;
public async Task<List<string>> GetFilesAsync(string directory, CancellationTokenSource cancellationToken, IProgress<DirectoryAnalyserProgress> progress)
{
this._files = new List<string>();
this._directoryCounter = 0;
await this.GetFilesInternalAsync(directory, cancellationToken, progress);
return this._files;
}
private async Task GetFilesInternalAsync(string directory, CancellationTokenSource cancellationToken, IProgress<DirectoryAnalyserProgress> progress)
{
if (cancellationToken.IsCancellationRequested)
{
return;
}
if (!this.CanRead(directory))
{
return;
}
this._files.AddRange(Directory.GetFiles(directory));
this._directoryCounter++;
progress?.Report(new DirectoryAnalyserProgress()
{
DirectoriesSearched = this._directoryCounter,
FilesFound = this._files.Count
});
foreach (var subDirectory in Directory.GetDirectories(directory))
{
await this.GetFilesInternalAsync(subDirectory, cancellationToken, progress);
}
}
public bool CanRead(string path)
{
var readAllow = false;
var readDeny = false;
var accessControlList = Directory.GetAccessControl(path);
if (accessControlList == null)
{
return false;
}
var accessRules = accessControlList.GetAccessRules(true, true, typeof(SecurityIdentifier));
if (accessRules == null)
{
return false;
}
foreach (FileSystemAccessRule rule in accessRules)
{
if ((FileSystemRights.Read & rule.FileSystemRights) != FileSystemRights.Read)
{
continue;
}
if (rule.AccessControlType == AccessControlType.Allow)
{
readAllow = true;
}
else if (rule.AccessControlType == AccessControlType.Deny)
{
readDeny = true;
}
}
return readAllow && !readDeny;
}
}
public class DirectoryAnalyserProgress
{
public int FilesFound { get; set; }
public int DirectoriesSearched { get; set; }
}
公共类目录分析器
{
私有列表文件;
专用int_目录计数器;
公共异步任务GetFileAsync(字符串目录、CancellationTokenSource cancellationToken、IProgress进度)
{
此._files=new List();
此._directoryCounter=0;
等待这个.GetFilesInternalAsync(目录、cancellationToken、进度);
返回此文件。\u文件;
}
专用异步任务GetFilesInternalAsync(字符串目录、CancellationTokenSource cancellationToken、IProgress进度)
{
if(cancellationToken.IsCancellationRequested)
{
返回;
}
如果(!this.CanRead(目录))
{
返回;
}
这个.u files.AddRange(Directory.GetFiles(Directory));
这是._directoryCounter++;
进度?报告(新的DirectoryAnalyzerProgress()
{
DirectoriesArched=此.\u directoryCounter,
FilesFound=this.\u files.Count
});
foreach(目录中的var子目录。GetDirectories(目录))
{
等待这个.getFileInternalAsync(子目录,cancellationToken,progress);
}
}
公共布尔值可读取(字符串路径)
{
var readAllow=false;
var readDeny=false;
var accessControlList=Directory.GetAccessControl(路径);
if(accessControlList==null)
{
返回false;
}
var accessRules=accessControlList.GetAccessRules(true,true,typeof(SecurityIdentifier));
if(accessRules==null)
{
返回false;
}
foreach(accessRules中的FileSystemAccessRule规则)
{
if((FileSystemRights.Read&rule.FileSystemRights)!=FileSystemRights.Read)
{
继续;
}
if(rule.AccessControlType==AccessControlType.Allow)
{
readAllow=true;
}
else if(rule.AccessControlType==AccessControlType.Deny)
{
readDeny=true;
}
}
返回readAllow&!readDeny;
}
}
公共类DirectoryAnalyzerProgress
{
找到公共int文件{get;set;}
公共int目录搜索{get;set;}
}
在标记重复的过程中,请留下评论。我的记事本上有25个以上的链接,我无法提供一个例子来说明为什么这些问题的每一个答案都不适用。但是我真的试过了。你接受了异常,但仍然继续计算foreach
。我不认为返回f
可以抛出异常,使try
/catch
无效。@KennethK.,在上一个代码中?对那只是一次尝试。如果目录.enumerate文件(当前路径,搜索模式)
。返回一个文件的错误,我没有办法跳过它。但是只跳过这个文件。不,整个目录都没有。而这一尝试也错过了子目录中的子目录dir@BradleyUffner是的,没错。错误出现在选择的之前。这段代码是对我不想做的事情的最好解释,即使这是一次失败的尝试。这是一个简单的插图purpuse.Hi,正如预期的this.\u files.AddRange(Directory.GetFiles(Directory))代码>不起作用。或者更确切地说是Directory.GetFiles(Directory)
如果其中一个文件太机密,则不返回任何内容。在var testSO=Directory.GetFiles(“c:\\$Recycle.Bin”)上尝试代码>不要被你的资源管理器破坏这个目录。
public class DirectoryAnalyser
{
private List<string> _files;
private int _directoryCounter;
public async Task<List<string>> GetFilesAsync(string directory, CancellationTokenSource cancellationToken, IProgress<DirectoryAnalyserProgress> progress)
{
this._files = new List<string>();
this._directoryCounter = 0;
await this.GetFilesInternalAsync(directory, cancellationToken, progress);
return this._files;
}
private async Task GetFilesInternalAsync(string directory, CancellationTokenSource cancellationToken, IProgress<DirectoryAnalyserProgress> progress)
{
if (cancellationToken.IsCancellationRequested)
{
return;
}
if (!this.CanRead(directory))
{
return;
}
this._files.AddRange(Directory.GetFiles(directory));
this._directoryCounter++;
progress?.Report(new DirectoryAnalyserProgress()
{
DirectoriesSearched = this._directoryCounter,
FilesFound = this._files.Count
});
foreach (var subDirectory in Directory.GetDirectories(directory))
{
await this.GetFilesInternalAsync(subDirectory, cancellationToken, progress);
}
}
public bool CanRead(string path)
{
var readAllow = false;
var readDeny = false;
var accessControlList = Directory.GetAccessControl(path);
if (accessControlList == null)
{
return false;
}
var accessRules = accessControlList.GetAccessRules(true, true, typeof(SecurityIdentifier));
if (accessRules == null)
{
return false;
}
foreach (FileSystemAccessRule rule in accessRules)
{
if ((FileSystemRights.Read & rule.FileSystemRights) != FileSystemRights.Read)
{
continue;
}
if (rule.AccessControlType == AccessControlType.Allow)
{
readAllow = true;
}
else if (rule.AccessControlType == AccessControlType.Deny)
{
readDeny = true;
}
}
return readAllow && !readDeny;
}
}
public class DirectoryAnalyserProgress
{
public int FilesFound { get; set; }
public int DirectoriesSearched { get; set; }
}