tags:

views:

73

answers:

2

I recently came across a problem with My.Computer.FileSystem.DeleteDirectory(). It will not delete read only files.

I found out by Googling that I could delete the read only files by changing the file attributes to 'Normal'. So I wrote a recursive function, as below.

Private Sub DeleteDir(ByVal dir As DirectoryInfo)

    For Each d In dir.GetDirectories
        DeleteDir(d)
    Next
    For Each f In dir.GetFiles
        Try
            f.Attributes = FileAttributes.Normal
            f.Delete()
        Catch ex As Exception
            Log(ex.Message)
        End Try
    Next
    dir.Delete(True)
End Sub

It seems to work fine, but it would be nice if My.Computer.FileSystem.DeleteDirectory() had another parameter to delete read only files, or there was an easier way to do this.

A: 

My understanding is that the classes in the My namespace are partly meant as a crutch to new developers (possibly with a VB6 background) that finds the .Net framework a bit overwhelming. If they made the My namespace too big, I think it would defeat that purpose of being easier to find things in. I would also assume that they probably had limited resources to build that namespace and had to be quite selective.

The solution is for you to do as you've done and write your own method, which you could then put in a class library or similar together with other helpful helper functions that you can then easily include in all your projects.

Btw, remember that dir.Delete(True) can throw exceptions as well.

ho1
A: 

The short answer is there isn't a method provided in the framework. You have to develop your own. What you have written is good. I prefer the following as it make use of extension methods and more clearly describes what the method does.

Imports System
Imports System.IO
Imports System.Runtime.CompilerServices
Imports System.Linq

Public Module DirectoryExtensions

    <Extension()>
    Public Sub Delete(directory As DirectoryInfo, 
                      recursive As Boolean, 
                      forceReadOnlyDelete As Boolean
    )
        directory.ForceDelete()
    End Sub

    <Extension()>
    Public Sub ForceDelete(ByVal directory As DirectoryInfo)

        directory.RemoveReadOnlyAttributeFromFiles(True)
        directory.Delete(True)

    End Sub

    <Extension()>
    Public Sub RemoveReadOnlyAttributeFromFiles(ByVal directory As DirectoryInfo, ByVal recursive As Boolean)

        Dim readOnlyFiles = From f In directory.GetFiles()
            Where (f.Attributes And FileAttributes.ReadOnly) = FileAttributes.ReadOnly

        For Each file In readOnlyFiles
            file.Attributes = FileAttributes.Normal
        Next

        If recursive Then

            For Each subDirectory In directory.GetDirectories()
                subDirectory.RemoveReadOnlyAttributeFromFiles(True)
            Next

        End If

    End Sub

End Module
Tim Murphy
Thanks Tim, I learned a bit about Extensions through your post. It would be nice to polymorph the current Delete and add an extra boolean parameter "force_read_only_delete" or something like that. Can you polymorph through Extensions? That could be another question :)
Rots
Yes you can. I've add an example to the existing code.
Tim Murphy