すべての構造を持つフォルダーを再帰的に削除するコードを作成しました。
から取得System.IO.DirectoryNotFoundException
しFile.Delete
た有効なファイル名を取得しましたDirectory.GetFiles(path)
。以前に追加File.Exists
したところ、ファイルが存在しないか、エクスプローラーで表示できることがわかりました。
私はそれがうまくいくSHFileOperation
はずだと知っています。しかし、ネイティブ C# を使用したいと思います (直接の Windows API ではありません)。
赤: Windows 10 で .NET 4.6.2 と長いパスを設定し、ローカル グループ ポリシー エディターで [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; }
更新 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;
}
// ******************************************************************
}
}