1

我在使用FileInfo.Delete()Directory.Delete(path, true)复制文件夹时发现了一个非常奇怪的错误。

问题:

  • 递归复制包含许多文件和一些子文件夹的文件夹
  • 尝试递归删除原文件夹
  • 恰好在文件夹内的第三个文件上,应用程序将崩溃而不会抛出Exception
  • 它并不总是同一个文件,因为前两个被正常删除,第三个失败。(如果我再试一次,第一个将是最后一个失败的,并且会成功删除)

再生产:

WPF应用程序中,具有以下方法的按钮会导致崩溃(稍后我将尝试在控制台应用程序中重现):

private void Tester_Click(object sender, RoutedEventArgs e)
{
    string copyFolderToThisPath = @"C:\Users\xxx\Desktop\xxxx\xxxx_xxx - Copia";
    string copyAndDeleteThisFolder = @"C:\Users\xxx\Desktop\xxxx\Prov\Nova pasta (3)";

    //copy the directory recursively: works
    CopyOrDeleteDirectory(new DirectoryInfo(copyAndDeleteThisFolder), copyFolderToThisPath);

    //delete the directory recursively: fails at the third file of the main folder - always
    CopyOrDeleteDirectory(new DirectoryInfo(copyAndDeleteThisFolder), null);
}

递归复制或删除:(
我知道Directory.Delete(path, true)存在,但它也失败了,我创建了递归删除来检查发生了什么)

/// <summary>
/// Copies or deletes a directory recursively - Use copyToPath == null to delete
/// </summary>
/// <param name="copyToPath">Destination to copy. If null, will delete the directory</param>
/// <returns>true if all operations with this directory were successful</returns>
private bool CopyOrDeleteDirectory(DirectoryInfo directory, string copyToPath)
{
    bool isCopy = !string.IsNullOrEmpty(copyToPath); //defines if the method will copy or delete

    FileInfo[] files = null;
    DirectoryInfo[] dirs = null;

    //try get files and subdirectories
    try
    {
        files = directory.GetFiles();
        dirs = directory.GetDirectories();

        if (isCopy)
            Directory.CreateDirectory(copyToPath);
    }
    catch (Exception e)
    {
        MessageBox.Show("Could not enumerate folder " + directory.Name);
        return false;
    }
    

    bool success = true;

    //copy or delete files
    foreach (FileInfo file in files)
    {
        try
        {
            if (isCopy)
                file.CopyTo(System.IO.Path.Combine(copyToPath, file.Name));
            else
                file.Delete(); //exactly at the third iteration it will crash the application
        }
        catch (Exception e) //the exception will NEVER be thrown!! Catch block is not reached
        {
            MessageBox.Show("Failed to operate file " + file.Name);
            success = false;
        }
    }


    //copy or delete subdirectories
    foreach (DirectoryInfo d in dirs)
    {
        try
        {
            string subPath = isCopy ? System.IO.Path.Combine(copyToPath, d.Name) : null;
            bool subDirSuccess = CopyOrDeleteDirectory(d, subPath);

            if (!subDirSuccess)
                success = false;
        }
        catch (StackOverflowException ex)
        {
            MessageBox.Show("StackOverflow in recursive function");
            success = false;
        }
    }

    if (success && (!isCopy))
    {
        try
        {
            directory.Delete();
        }
        catch (Exception e)
        {
            MessageBox.Show("Failed to delete directory " + directory.Name);
            success = false;
        }
    }

    return success;
}

重要细节:

  • 这是一个“错误再现”代码。原来的应用比较大,复制和删除之间有与用户的交互。这种“复制和删除”不是应用程序的正常流程,但用户可以通过调用应用程序的两个不同命令来做到这一点
  • 在用户单击复制和单击删除之间,应用程序完全响应有一个时间间隔。复制操作在用户可以做任何其他事情之前完成。
  • 如果只调用delete命令不会出现问题,如果先有副本就会出现问题
  • 我尝试释放资源,但似乎无法用于FileInfoand DirectoryInfo。无论如何,我尝试尽快将所有内容设置为 null ,但没有成功。
  • 没有Exception抛出,应用程序完全崩溃
  • 所有文件都可以访问,没有一个是只读的
  • 视窗 10
  • 使用 C# 的 WPF 应用程序
  • Visual Studio 2017 调试(问题发生在步进与否)
4

0 回答 0