![](/img/trans.png)
[英]System.IO.DirectoryNotFoundException by File.Move
[英]System.IO.DirectoryNotFoundException on File.Delete for a valid path
我寫了代碼來遞歸刪除所有結構的文件夾。
我在File.Delete
上獲得了System.IO.DirectoryNotFoundException
以File.Delete
從Directory.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.