访问路径';d: $RECYCLE.BINS-5-21-494745725-312220573-77495

本文关键字:RECYCLE BINS-5-21-494745725-312220573-77495 路径 访问 | 更新日期: 2023-09-27 18:28:24

我是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
        }
}

请帮我解决。感谢

访问路径';d: $RECYCLE.BINS-5-21-494745725-312220573-77495

在可能包含不可访问子文件夹的文件夹上搜索时,最重要的规则是:

不要使用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, "*");

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

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

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

正如Ian在他的文章中所指出的,在类似于您的情况下,不要使用递归文件列表(Directory.GetFiles(path, searchPattern, SearchOption.AllDirectories)),因为第一个异常将停止进一步处理。

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

此外,您应该使用下面这样的代码来进行搜索,这样中间的异常不会停止进一步的搜索。

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