访问路径' d:\ $ RECYCLE.BIN \ S-1-5-21-494745725-312220573-749543506-41600'被拒绝

时间:2015-12-30 07:39:55

标签: c#

我是C#的新手。我有一个文本框,我输入要搜索的文件,然后搜索'按钮。在搜索时钟我希望它填充文件夹中的文件,但我得到上述错误。以下是我的代码:

string[] directories = Directory.GetDirectories(@"d:\",
                                              "*",
                                              SearchOption.AllDirectories);
string file = textBox1.Text;
DataGrid dg = new DataGrid();

{
    var files = new List<string>();
     foreach (DriveInfo d in DriveInfo.GetDrives().Where(x => x.IsReady))
        {
        try
        {
            files.AddRange(Directory.GetFiles(d.RootDirectory.FullName,  file , SearchOption.AllDirectories));
        }
        catch(Exception ex)
        {
            MessageBox.Show("the  exception is " + ex.ToString());
            //Logger.Log(e.Message); // Log it and move on
        }
}

请帮我解决。感谢

2 个答案:

答案 0 :(得分:2)

搜索可能包含无法访问的子文件夹的文件夹时,

最重要的规则是:

  

使用SearchOption.AllDirectories

使用SearchOption.TopDirectoryOnly代替递归搜索,用于所有可访问的目录。

使用SearchOption.AllDirectories一次访问冲突将在处理任何文件/目录之前破坏整个循环。但是,如果您使用SearchOption.TopDirectoryOnly,则只会跳过无法访问的内容。

每个子目录检查使用Directory.GetAccessControl()有一种更困难的方法,看看你是否可以预先访问目录(这个选项相当困难 - 除非你真的推荐这个确切地知道访问系统是如何工作的。)

对于递归搜索,我将此代码实现为自己使用:

public static List<string> GetAllAccessibleDirectories(string path, string searchPattern) {
    List<string> dirPathList = new List<string>();
    try {
        List<string> childDirPathList = Directory.GetDirectories(path, searchPattern, SearchOption.TopDirectoryOnly).ToList(); //use TopDirectoryOnly
        if (childDirPathList == null || childDirPathList.Count <= 0) //this directory has no child
            return null;
        foreach (string childDirPath in childDirPathList) { //foreach child directory, do recursive search
            dirPathList.Add(childDirPath); //add the path
            List<string> grandChildDirPath = GetAllAccessibleDirectories(childDirPath, searchPattern);
            if (grandChildDirPath != null && grandChildDirPath.Count > 0) //this child directory has children and nothing has gone wrong
                dirPathList.AddRange(grandChildDirPath.ToArray()); //add the grandchildren to the list
        }
        return dirPathList; //return the whole list found at this level
    } catch {
        return null; //something has gone wrong, return null
    }
}

这就是你怎么称呼它

List<string> accessibleDirs = GetAllAccessibleDirectories(myrootpath, "*");

然后,您只需要在所有可访问目录中搜索/添加文件。

注意:这个问题非常经典。我相信还有一些其他更好的解决方案。

如果在获得所有可访问的目录后有一些特别想要避免的目录,您还可以使用目录的部分名称作为关键字来过滤LINQ的List结果(即Recycle.Bins)。

答案 1 :(得分:1)

正如Ian在他的post中指定的那样,请不要使用递归文件列表(Directory.GetFiles(path, searchPattern, SearchOption.AllDirectories)),因为第一个异常将停止进一步处理。

此外,为了在某种程度上缓解此类问题并获得更好的结果,您应该将此程序作为Administrator运行。这可以通过在Windows资源管理器中右键单击您的应用程序,然后选中Run this program as an administrator选项卡上的Compatibility选项来完成。

此外,您应该使用以下代码进行搜索,因此中间异常不会停止进一步搜索。

static void Main(string[] args) {
    string fileToFind = "*.jpg";
    var files = new List<string>();

    foreach (DriveInfo d in DriveInfo.GetDrives().Where(x => x.IsReady))
        files.AddRange(FindDirectory(fileToFind, d.RootDirectory.FullName));
}

/// <summary>
/// This function returns the full file path of the matches it finds. 
///   1. It does not do any parameter validation 
///   2. It searches recursively
///   3. It eats up any error that occurs when requesting files and directories within the specified path
///   4. Supports specifying wildcards in the fileToFind parameter.
/// </summary>
/// <param name="fileToFind">Name of the file to search, without the path</param>
/// <param name="path">The path under which the file needs to be searched</param>
/// <returns>Enumeration of all valid full file paths matching the file</returns>
public static IEnumerable<string> FindDirectory(string fileToFind, string path) {

    // Check if "path" directly contains "fileToFind"
    string[] files = null;
    try {
        files = Directory.GetFiles(path, fileToFind);
    } catch { }

    if (files != null) {
        foreach (var file in files)
            yield return file;
    }


    // Check all sub-directories of "path" to see if they contain "fileToFInd"
    string[] subDirs = null;
    try {
        subDirs = Directory.GetDirectories(path);
    } catch { }

    if (subDirs == null)
        yield break;

    foreach (var subDir in subDirs)
        foreach (var foundFile in FindDirectory(fileToFind, subDir))
            yield return foundFile;
}