簡體   English   中英

File.Delete上的System.IO.DirectoryNotFoundException為有效路徑

[英]System.IO.DirectoryNotFoundException on File.Delete for a valid path

我寫了代碼來遞歸刪除所有結構的文件夾。

我在File.Delete上獲得了System.IO.DirectoryNotFoundExceptionFile.DeleteDirectory.GetFiles(path)獲得的有效文件名。 我之前添加了File.Exists ,它告訴我該文件不存在,也可以在資源管理器中看到它。

我知道我可以使用SHFileOperation做到這一點,應該可以正常工作。 但是我想使用本機C#(無直接Windows API)。

我紅色: .NET 4.6.2和Windows 10上的長路徑,並在本地組策略編輯器中設置啟用“啟用Win 32長路徑”。

我正在使用.NET Framework 4.7.2。

誰能告訴我我的代碼有什么問題嗎? 還是我能做些什么才能使其起作用?

錯誤的路徑是:

'E:\\ CobianBackupOld \\ cn1629 \\ AppData \\ Local \\ Packages \\ Microsoft.Windows.Cortana_cw5n1h2txyewy \\ LocalState \\ AppIconCache \\ 100 \\ {7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E} _Microsoft Visual Studio 9_0_Application_fuEmpator控件版本

我是該文件的所有者(我確實有權刪除它)。

更新

我部分修復了我的錯誤,但想知道如何正確修復它(最近的框架應該支持長路徑嗎?)。 我的實際解決方法是在遞歸函數的開頭添加該代碼

 if (path.Length < 2 || !path.StartsWith(@"\\\\")) { path = @"\\\\?\\" + path; } 

更新2雖然沒有直接關系...只是要指出一個重點,C#File.Delete或Directory.Delete不會刪除只讀文件或文件夾,您還應該在刪除它們之前將其權限更改為普通權限,否則將獲得訪問權限拒絕錯誤。

僅供參考,我的代碼是:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HQ.Util.General.IO
{
    public class DirectoryRemoverRecursive
    {
        private readonly Action<string, string> _pathStatus;
        private readonly Func<string, bool> _callbackCanRemoveFile;
        private readonly Func<string, bool> _callbackCanRemoveFolder;
        private Func<bool> _shouldCancel;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pathStatus">Arguments are [path] and [null on success or exception message]</param>
        /// <param name="callbackCanRemoveFile">Argument is path and should return true to delete. If this function is null, all path will be deleted.</param>
        /// <param name="callbackCanRemoveFolder">Argument is path and should return true to delete. If this function is null, all path will be deleted.</param>
        /// <param name="shouldCancel">If null will never cancel. Cancel when func return true</param>
        public DirectoryRemoverRecursive(
            Action<string, string> pathStatus = null, 
            Func<string, bool> callbackCanRemoveFile = null, 
            Func<string, bool> callbackCanRemoveFolder = null, 
            Func<bool> shouldCancel = null)
        {
            _pathStatus = pathStatus;
            _callbackCanRemoveFile = callbackCanRemoveFile;
            _callbackCanRemoveFolder = callbackCanRemoveFolder;
            _shouldCancel = shouldCancel;
        }

        // ******************************************************************
        /// <summary>
        /// return true if canceled
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public bool Remove(string path)
        {
            string result = null;

            if (Directory.Exists(path))
            {
                foreach (var subDir in Directory.GetDirectories(path))
                {
                    if (_shouldCancel != null)
                    {
                        if (_shouldCancel())
                        {
                            return true;
                        }
                    }

                    if (Remove(subDir))
                    {
                        return true;
                    }
                }

                foreach (var filename in Directory.GetFiles(path))
                {
                    if (_shouldCancel != null)
                    {
                        if (_shouldCancel())
                        {
                            return true;
                        }
                    }

                    if (Remove(filename))
                    {
                        return true;
                    }
                }

                try
                {
                    if (_callbackCanRemoveFolder != null)
                    {
                        if (!_callbackCanRemoveFolder(path))
                        {
                            return false;
                        }
                    }

                    Directory.Delete(path);
                    result = null;
                }
                catch (Exception ex)
                {
                    result = ex.Message;
                }
            }
            else
            {
                try
                {
                    if (File.Exists(path))
                    {
                        if (_callbackCanRemoveFile != null)
                        {
                            if (!_callbackCanRemoveFile(path))
                            {
                                return false;
                            }
                        }

                        File.Delete(path);
                        result = null;
                    }
                    else
                    {
                        Debug.Print($"File does not exists {path}");
                    }
                }
                catch (Exception ex)
                {
                    result = ex.Message;
                }
            }

            _pathStatus?.Invoke(path, result);

            return false;
        }

        // ******************************************************************

    }

}

盡管沒有我希望的那么完美,但我通過使用前綴“ \\?\\”並確保在刪除之前將屬性設置為normal來修復了我的錯誤。

我仍然不明白,為什么我仍然必須這樣做??? 為什么在最近的.net庫中仍未修復該問題?

最終代碼:

using System;
using System.Diagnostics;
using System.IO;

namespace HQ.Util.General.IO
{
    public class DirectoryRemoverRecursive
    {
        private readonly Action<string, string, int> _pathStatus;
        private readonly Func<string, bool> _callbackCanRemoveFile;
        private readonly Func<string, bool> _callbackCanRemoveFolder;
        private Func<bool> _shouldCancel;

        public int Count { get; private set; } = 0;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pathStatus">Arguments are [path] and [null on success or exception message]</param>
        /// <param name="callbackCanRemoveFile">Argument is path and should return true to delete. If this function is null, all path will be deleted.</param>
        /// <param name="callbackCanRemoveFolder">Argument is path and should return true to delete. If this function is null, all path will be deleted.</param>
        /// <param name="shouldCancel">If null will never cancel. Cancel when func return true</param>
        public DirectoryRemoverRecursive(
            Action<string, string, int> pathStatus = null, 
            Func<string, bool> callbackCanRemoveFile = null, 
            Func<string, bool> callbackCanRemoveFolder = null, 
            Func<bool> shouldCancel = null)
        {
            _pathStatus = pathStatus;
            _callbackCanRemoveFile = callbackCanRemoveFile;
            _callbackCanRemoveFolder = callbackCanRemoveFolder;
            _shouldCancel = shouldCancel;
        }

        // ******************************************************************
        /// <summary>
        /// return true if canceled
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public bool Remove(string path)
        {
            string result = null;

            if (path.Length < 2 || !path.StartsWith(@"\\"))
            {
                path = @"\\?\" + path;
            }

            if (Directory.Exists(path))
            {
                foreach (var subDir in Directory.GetDirectories(path))
                {
                    if (_shouldCancel != null)
                    {
                        if (_shouldCancel())
                        {
                            return true;
                        }
                    }

                    if (Remove(subDir))
                    {
                        return true;
                    }
                }

                foreach (var filename in Directory.GetFiles(path))
                {
                    if (_shouldCancel != null)
                    {
                        if (_shouldCancel())
                        {
                            return true;
                        }
                    }

                    if (Remove(filename))
                    {
                        return true;
                    }
                }

                try
                {
                    if (_callbackCanRemoveFolder != null)
                    {
                        if (!_callbackCanRemoveFolder(path))
                        {
                            return false;
                        }
                    }

                    Directory.Delete(path);
                    Count++;
                    result = null;
                }
                catch (Exception ex)
                {
                    try
                    {
                        File.SetAttributes(path, FileAttributes.Normal);
                        Directory.Delete(path);
                        Count++;
                        result = null;
                    }
                    catch (Exception)
                    {
                        result = "Try to delete directory exception: " + ex.ToString();
                    }
                }
            }
            else
            {
                try
                {
                    if (File.Exists(path))
                    {
                        if (_callbackCanRemoveFile != null)
                        {
                            if (!_callbackCanRemoveFile(path))
                            {
                                return false;
                            }
                        }

                        File.Delete(path);
                        Count++;
                        result = null;
                    }
                    else
                    {
                        Debug.Print($"File does not exists {path}");
                    }
                }
                catch (Exception ex)
                {
                    try
                    {
                        File.SetAttributes(path, FileAttributes.Normal);
                        File.Delete(path);
                        Count++;
                        result = null;
                    }
                    catch (Exception)
                    {
                        result = "Try to delete file exception: " + ex.ToString();
                    }
                }
            }

            _pathStatus?.Invoke(path, result, Count);

            return false;
        }

        // ******************************************************************

    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM