C# 忽略Directory.Enumerate文件的异常,跳过这些文件

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

在枚举时,我想跳过/忽略异常

我尝试在选择器中添加一个try catch:

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; }
}