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

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

フォルダを作成、削除、移動(名前の変更)する」で説明したように、Directory.Deleteメソッドを使うと、フォルダとそれ以下にあるすべてのファイルとフォルダを削除することができます。しかしこの時、削除するフォルダ以下に読み取り専用属性のファイルやフォルダがあると、例外UnauthorizedAccessExceptionをスローして、削除に失敗します。ここでは、この対策について説明します。

削除する前に読み取り専用属性を外す方法

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);
}

My.Computer.FileSystem.DeleteDirectoryメソッドを使用する方法

.NET Framework 2.0以降のVB.NETでは、My.Computer.FileSystem.DeleteDirectoryメソッドでフォルダを削除することもできます。DeleteDirectoryメソッドでは、引数にUIOption列挙体の値を指定すれば、読み取り専用ファイルがあっても削除します。

このメソッドは、C#でも「Microsoft.VisualBasic.dll」を参照設定に追加すれば、FileSystem.DeleteDirectoryメソッドとして使用することができます。

DeleteDirectoryメソッドにUIOptionを指定して呼び出した時は、それ以上の機能も使用できます。例えばエクスプローラでフォルダを削除したときのように、「削除しています...」ダイアログで進行状況を表示したり、ユーザーが途中で処理をキャンセルできたり、削除したファイルをごみ箱に入れたりすることもできます。詳しくは「フォルダを作成、削除、移動(名前の変更)する」で説明していますので、そちらをご覧ください。

以下に、FileSystem.DeleteDirectoryメソッドを使って"C:\A"フォルダを削除する例を示します。進行状況ダイアログを表示するためにUIOption.AllDialogsを、ごみ箱に入れるためにRecycleOption.SendToRecycleBinを、ユーザーがキャンセルしても例外OperationCanceledExceptionをスローしないように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 ???; がソースファイルの一番上に書かれているものとする」)の意味が分からないという方は、こちらをご覧ください。
  • 「???を参照に追加します」の意味が分からないという方は、こちらをご覧ください。
  • Windows Vista以降でUACが有効になっていると、ファイルへの書き込みに失敗する可能性があります。詳しくは、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。