DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

DOBON.NET

読み取り専用ファイルがあるときでもフォルダを削除する

Directory.Deleteメソッドにより、ファイルやサブフォルダのあるフォルダを根こそぎ削除することができますが、この時、削除するフォルダ以下に読み取り専用属性のファイルやフォルダがあると、削除に失敗します。これを防ぐためには、Directory.Deleteメソッドを呼び出す前にすべてのファイルとフォルダの読み取り専用属性を外しておきます。

以下に示すDeleteDirectoryメソッドでは、フォルダを削除する前に、そのフォルダ以下のすべてのファイルとフォルダを調べ、読み取り専用属性を外しています。

[VB.NET]
'Imports System.IO
'がソースファイルの一番上に書かれているものとする

''' <summary>
''' フォルダを根こそぎ削除する(ReadOnlyでも削除)
''' </summary>
''' <param name="dir">削除するフォルダ</param>
Public Shared Sub DeleteDirectory(ByVal dir As String)
    'DirectoryInfoオブジェクトの作成
    Dim di As New DirectoryInfo(dir)

    'フォルダ以下のすべてのファイル、フォルダの属性を削除
    RemoveReadonlyAttribute(di)

    'フォルダを根こそぎ削除
    di.Delete(True)
End Sub

Public Shared Sub RemoveReadonlyAttribute( _
        ByVal dirInfo As DirectoryInfo)
    '基のフォルダの属性を変更
    If (dirInfo.Attributes And FileAttributes.ReadOnly) =
        FileAttributes.ReadOnly Then
        dirInfo.Attributes = FileAttributes.Normal
    End If
    'フォルダ内のすべてのファイルの属性を変更
    Dim fi As FileInfo
    For Each fi In dirInfo.GetFiles()
        If (fi.Attributes And FileAttributes.ReadOnly) =
            FileAttributes.ReadOnly Then
            fi.Attributes = FileAttributes.Normal
        End If
    Next fi
    'サブフォルダの属性を回帰的に変更
    Dim di As DirectoryInfo
    For Each di In dirInfo.GetDirectories()
        RemoveReadonlyAttribute(di)
    Next di
End Sub
[C#]
//using System.IO;
//がソースファイルの一番上に書かれているものとする

/// <summary>
/// フォルダを根こそぎ削除する(ReadOnlyでも削除)
/// </summary>
/// <param name="dir">削除するフォルダ</param>
public static void DeleteDirectory(string dir)
{
    //DirectoryInfoオブジェクトの作成
    DirectoryInfo di = new DirectoryInfo(dir);

    //フォルダ以下のすべてのファイル、フォルダの属性を削除
    RemoveReadonlyAttribute(di);

    //フォルダを根こそぎ削除
    di.Delete(true);
}

public static void RemoveReadonlyAttribute(DirectoryInfo dirInfo)
{
    //基のフォルダの属性を変更
    if ((dirInfo.Attributes & FileAttributes.ReadOnly) ==
        FileAttributes.ReadOnly)
        dirInfo.Attributes = FileAttributes.Normal;
    //フォルダ内のすべてのファイルの属性を変更
    foreach (FileInfo fi in dirInfo.GetFiles())
        if ((fi.Attributes & FileAttributes.ReadOnly) ==
            FileAttributes.ReadOnly)
            fi.Attributes = FileAttributes.Normal;
    //サブフォルダの属性を回帰的に変更
    foreach (DirectoryInfo di in dirInfo.GetDirectories())
        RemoveReadonlyAttribute(di);
}

.NET Framework 2.0以降で、My.Computer.FileSystem.DeleteDirectoryメソッドを使用する方法

.NET Framework 2.0以降のVB.NETでは、My.Computer.FileSystem.DeleteDirectoryメソッドでフォルダを削除することもできます。DeleteDirectoryメソッドでは、読み取り専用ファイルの削除もできます。それだけでなく、エクスプローラでフォルダを削除したときのように、「削除しています...」ダイアログにより進行状況を表示し、ユーザーがキャンセルすることもできます。しかも、削除したファイルをごみ箱に入れることもできます。

補足:My.Computer.FileSystem.DeleteDirectoryメソッドは、ユーザーインターフェイスやごみ箱機能を使用する時は、SHFileOperation関数を使用します。そうでなければ、Direcrory.Deleteを使用することもあるようです。

次に"C:\A"フォルダを削除する例を示します。進行状況ダイアログを表示するためにUIOption.AllDialogsを指定し(デフォルトでは表示されない)、ごみ箱に入れるためにRecycleOption.SendToRecycleBinを指定し(デフォルトでは入れない)、ユーザーがキャンセルしても例外(IOException)をスローしないようにUICancelOption.DoNothingを指定しています(デフォルトでは、スローされる)。

[VB.NET]
'ディレクトリ"C:\A"を削除する
My.Computer.FileSystem.DeleteDirectory("C:\A", _
    FileIO.UIOption.AllDialogs, _
    FileIO.RecycleOption.SendToRecycleBin, _
    FileIO.UICancelOption.DoNothing)
[C#]
//参照にMicrosoft.VisualBasic.dllが追加されている必要がある

//ディレクトリ"C:\A"を削除する
Microsoft.VisualBasic.FileIO.FileSystem.DeleteDirectory(
    "C:\\A",
    Microsoft.VisualBasic.FileIO.UIOption.AllDialogs,
    Microsoft.VisualBasic.FileIO.RecycleOption.SendToRecycleBin,
    Microsoft.VisualBasic.FileIO.UICancelOption.DoNothing);
  • 履歴:
  • 2006/12/11, 2006/12/22 属性の変更が正しく行われない不具合を修正。
  • 2007/2/19 My.Computer.FileSystem.DeleteDirectoryメソッドを使用する方法を追加。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • コードの先頭に記述されている「Imports ??? がソースファイルの一番上に書かれているものとする」(C#では、「using ???; がソースファイルの一番上に書かれているものとする」)の意味が分からないという方は、こちらをご覧ください。
  • 「???を参照に追加します」の意味が分からないという方は、こちらをご覧ください。