我编写了代码以递归方式删除具有所有结构的文件夹。
我得到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_PreEmptive Solutions_Dotfuscator Community Edition_dotfuscator_exe'
我是该文件的所有者(我有权删除它)。
更新
我部分修复了我的错误,但想知道如何正确修复它(最近的框架应该支持长路径???)。我的实际解决方法是在我的递归函数开始时添加该代码
if (path.Length < 2 || !path.StartsWith(@"\\")) { path = @"\\?\" + path; }
UPDATE 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;
}
// ******************************************************************
}
}