C# 从不同方法调用DirectoryInfo时,返回不同的值

C# 从不同方法调用DirectoryInfo时,返回不同的值,c#,wpf,directoryinfo,C#,Wpf,Directoryinfo,我一直在开发一种目录信息查看器。 第一个阶段是创建和填充一个TreeView模型,在编码过程中,我嵌套了一个方法来收集关于该目录上文件的信息。 一切正常,返回的值正确,等等 现在,在代码清理阶段,当我尝试从TreeView创建中获取该方法时,我得到的值甚至不接近原始值(比如90MB而不是1.2TB) 以下代码标记了问题: private static int itemCount = 0; private static long folderSizeInfo = 0; public static

我一直在开发一种目录信息查看器。 第一个阶段是创建和填充一个TreeView模型,在编码过程中,我嵌套了一个方法来收集关于该目录上文件的信息。 一切正常,返回的值正确,等等

现在,在代码清理阶段,当我尝试从TreeView创建中获取该方法时,我得到的值甚至不接近原始值(比如90MB而不是1.2TB)

以下代码标记了问题:

private static int itemCount = 0;
private static long folderSizeInfo = 0;

public static void ListDirectory(string path)
    {
        (...)

        var rootDirectoryInfo = new DirectoryInfo(path);
        MainWindow.newWindowReport.Drzewko.Items.Add(CreateDirectoryNode(rootDirectoryInfo));

        //this does not work if invoked from here <----------------- FIX ME!
        //DirectoryMainOperation(rootDirectoryInfo);

        //need to run this once more to get data from root
        DirectoryContent_Operation(rootDirectoryInfo);

        (...)
    }

    private static TreeViewItem CreateDirectoryNode(DirectoryInfo directoryInfo)
    {
        var directoryNode = new TreeViewItem { Header = directoryInfo.Name };

        try
        {
            foreach (var directory in directoryInfo.GetDirectories())
            {
                if (!IsIgnorable(directory.Name))
                {
                    directoryNode.Items.Add(CreateDirectoryNode(directory));

                    //this method somehow only works here <------------------------ FIX ME!
                    DirectoryContent_Operation(directory);
                }
            }
        }
        catch (UnauthorizedAccessException)
        {
            //Console.WriteLine("Path is not accessible: {0}", i);
        }

        return directoryNode;
    }

    //-------------------TO BE FIXED------------------
    private static void DirectoryMainOperation(DirectoryInfo directoryInfo)
    {
        try
        {
            foreach (var directory in directoryInfo.GetDirectories())
            {
                if (!IsIgnorable(directory.Name))
                {
                    DirectoryContent_Operation(directory);
                }
            }
        }
        catch (UnauthorizedAccessException)
        {
            //Console.WriteLine("Path is not accessible: {0}", i);
        }
    }

    private static void DirectoryContent_Operation(DirectoryInfo targetDir)
    {
        try
        {
            foreach (var file in targetDir.EnumerateFiles("*", SearchOption.TopDirectoryOnly))
            {
                itemCount++;
                folderSizeInfo += file.Length;

                fileTable.Add(new FileExtension_List
                {
                    FileFormat = file.Extension,
                    Category = extDB.Translation(file.Extension.ToUpper()),
                    Count = 1,
                    TotalSize = file.Length
                });
            }
        }
        catch (UnauthorizedAccessException)
        {
        }
        catch (Exception ex)
        {
        }
    }
private static int itemCount=0;
私有静态长folderSizeInfo=0;
公共静态无效列表目录(字符串路径)
{
(...)
var rootDirectoryInfo=新目录信息(路径);
MainWindow.newWindowReport.Drzewko.Items.Add(CreateDirectoryNode(rootDirectoryInfo));

//如果从此处调用,则此操作不起作用。在DirectoryMainOperation中,由于
未经授权的访问异常
而过早返回,因此不会返回所有目录。在
DirectoryContent\u操作中
通过捕获
异常
来吞下每个异常

请删除try-catch(随处可见)以查看(内部)异常消息的确切内容以及引发异常的位置

请注意,吞咽异常始终是一种代码气味,可能会引入bug,这很难识别。
如果无法处理异常(将应用程序恢复到稳定状态),则应用程序必须崩溃。然后修复崩溃的原因。
在考虑是否以及如何处理异常之前,请考虑如何避免异常。
另外,从性能角度来看,强烈建议避免昂贵的异常

您的问题表明,让异常使应用程序崩溃对于了解实现错误以及防止不必要的静默副作用(如目录列表不完整)是多么重要。吞咽异常将使应用程序进入不可预测的状态,这将导致许多错误行为,这些行为可能是不可预测的这对于使用您的应用程序管理其业务的客户来说是非常昂贵的

为避免出现未经授权的访问异常,您可以使用DirectoryInfo.EnumerationDirectory(字符串、枚举选项)
,该选项仅适用于.NET Core(自2.1版起)。
默认情况下,它会跳过禁止的目录,从而避免引发
UnauthorizedAccessException
异常

或者,只枚举顶级目录。然后检查每个子目录(如果禁止),然后再继续递归枚举子目录的顶级目录。下面的递归枚举很可能会解决您的问题

public void ListDirectory(string path)
{
  var rootDirectoryInfo = new DirectoryInfo(path);    
  var rootDirectoryNode = new TreeViewItem { Header = directoryInfo.Name };     
  MainWindow.newWindowReport.Drzewko.Items.Add(rootDirectoryNode);
  CreateDirectoryNode(rootDirectoryInfo, rootDirectoryNode);
}

private static void CreateDirectoryNode(DirectoryInfo parentDirectory, TreeViewItem parentDirectoryNode)
{
  foreach (DirectoryInfo childDirectory in parentDirectory.EnumerateDirectories("*", SearchOption.TopDirectoryOnly))
  {
    var childDirectoryNode = new TreeViewItem { Header = childDirectory.Name };

    parentDirectoryNode.Items.Add(childDirectoryNode);

    // Don't enter forbidden directories
    // and optionally hidden directories too
    if (childDirectory.Attributes.HasFlag(FileAttributes.System) 
      || childDirectory.Attributes.HasFlag(FileAttributes.Hidden))
    {  
      continue;
    }

    // Recursively iterate over child's subdirectories
    CreateDirectoryNode(childDirectory, childDirectoryNode);
    DirectoryContent_Operation(childDirectory);
  }
}

private static void DirectoryMainOperation(DirectoryInfo parentDirectory)
{
  foreach (DirectoryInfo childDirectory in parentDirectory.EnumerateDirectories("*", SearchOption.TopDirectoryOnly))
  {
    if (!IsIgnorable(childDirectory.Name))
    {
      DirectoryContent_Operation(childDirectory);
    }

    // Don't enter forbidden directories 
    // and optionally hidden directories too
    if (childDirectory.Attributes.HasFlag(FileAttributes.System) 
      || childDirectory.Attributes.HasFlag(FileAttributes.Hidden))
    {  
      continue;
    }
    
    // Recursively iterate over child's subdirectories
    DirectoryMainOperation(childDirectory);
  }
}

通常更喜欢
DirectoryInfo.EnumerateDirectories
而不是
DirectoryInfo.GetDirectories

“如果从此处调用,则此操作无效”-这意味着什么?是否抛出错误?结果与您的预期有何不同?这些空捕获是否有可能隐藏重要信息?请注意,如果抛出异常,您的所有循环都将提前终止。“如果从此处调用,则此操作不起作用”表示如果从那里调用,则返回不正确的值。其要点是,如果我从“CreateDirectoryNode(DirectoryInfo DirectoryInfo)”运行“DirectoryContent\u操作(目录)”,则返回1.2 TB(正确值),如果我从“DirectoryMainOperation(rootDirectoryInfo)运行它”它返回90MB。正如@JeffE所指出的,您可能正在吞咽导致循环提前退出的异常-即,如果根目录包含无法枚举的文件或文件夹,那么您只能获得文件系统中问题项前面的目录的聚合结果循环部分我可以理解,但我不理解为什么会这样嵌套在方法A中时工作,在方法B中不工作-它们都以相同的方式构建(ctrl+c,ctrl+v)。它们具有相同的循环结构,具有相同的try/catch异常。