DeleteDirectory Throws Exception

Spectere

New member
Joined
Jan 29, 2007
Messages
4
Location
Ohio, USA
Programming Experience
10+
I'm having kind of an odd problem.

I'm using VB.NET (in VS2005, with .NET 2.0) to write a service (controlled by Group Policy) that allows me to delete user profiles regularly to save disk space on school lab computers (and keep their Documents and Settings directory nice and neat, not to mention continually "resetting" our generic student accounts) and in my test environment the program keeps continually throwing up IOExceptions. Here's an excerpt from the log file:


Deleting C:\Documents and Settings\student
Could not delete directory: C:\Documents and Settings\student
{exception: System.UnauthorizedAccessException: Access to the path 'C:\Documents and Settings\student\ntuser.pol' is denied.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.File.Delete(String path)
at Microsoft.VisualBasic.FileIO.FileSystem.DeleteFileInternal(String file, UIOptionInternal showUI, RecycleOption recycle, UICancelOption onUserCancel)
at Microsoft.VisualBasic.MyServices.FileSystemProxy.DeleteFile(String file)
at ProfilePurgeEngine.ProfilePurgeEngine.DeleteProfile(String path)}
Deleting C:\Documents and Settings\uteacher
Could not delete directory: C:\Documents and Settings\uteacher
{exception: System.UnauthorizedAccessException: Access to the path 'C:\Documents and Settings\uteacher\ntuser.pol' is denied.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.File.Delete(String path)
at Microsoft.VisualBasic.FileIO.FileSystem.DeleteFileInternal(String file, UIOptionInternal showUI, RecycleOption recycle, UICancelOption onUserCancel)
at Microsoft.VisualBasic.MyServices.FileSystemProxy.DeleteFile(String file)
at ProfilePurgeEngine.ProfilePurgeEngine.DeleteProfile(String path)}
Deleting C:\Documents and Settings\User
Could not delete directory: C:\Documents and Settings\User
{exception: System.IO.IOException: Access to the path 'C:\Documents and Settings\User\Application Data\Microsoft\Internet Explorer\Quick Launch' is denied.
at System.IO.Directory.DeleteHelper(String fullPath, String userPath, Boolean recursive)
at System.IO.Directory.Delete(String fullPath, String userPath, Boolean recursive)
at Microsoft.VisualBasic.FileIO.FileSystem.DeleteDirectoryInternal(String directory, DeleteDirectoryOption onDirectoryNotEmpty, UIOptionInternal showUI, RecycleOption recycle, UICancelOption onUserCancel)
at Microsoft.VisualBasic.MyServices.FileSystemProxy.DeleteDirectory(String directory, DeleteDirectoryOption onDirectoryNotEmpty)
at ProfilePurgeEngine.ProfilePurgeEngine.DeleteProfile(String path)}
This happens both with LOCAL SERVICE (when run as a service) and under a domain administrator account (when running the CLI version of this app).

The really odd part about this is that if I go in through Explorer/cmd.exe I can delete the said directories with no problem. The permissions are set up as they should be (Admininstrators, SYSTEM, and user having full control) and the files aren't being used (the ntuser.dat isn't being locked by Windows at this time) so there's no good reason that it shouldn't be working. Furthermore, it deletes about half of the contents before dying -- including the aforementioned registry file -- and the files that were actually deleted were the same between all of the test profiles.

The following code handles the deletion:

VB.NET:
        Try
            If Not pretend Then
                DebugOut("Deleting " + path)
 
                For Each file As String In Directory.GetFiles(path)
                    My.Computer.FileSystem.DeleteFile(file)
                Next
 
                My.Computer.FileSystem.DeleteDirectory(path, FileIO.DeleteDirectoryOption.DeleteAllContents)
            Else
                DebugOut("Not really deleting " + path)
            End If
        Catch ex As Exception
            DebugOut("Could not delete directory: " + path + vbNewLine + "{exception: " + ex.ToString + "}")
        End Try
As you can see, it's pretty simple and straight-forward.

Any ideas as to what the problem could be? I'm completely stumped.

Thanks!
 
Last edited by a moderator:
LocalService account is very restricted on system resources, you could try the LocalSystem account that has high privileges.

Not sure about your comment about administrator, I can see why a local administrator account wouldn't work.
 
I should probably explain how I designed the program. I ended up designing the program in three parts -- a DLL that does all of the work and a CLI application and service that interface with the main engine.

The local administrator thing has me kind of confused, especially seeing as I was able to just delete the directories manually. Even when run as LocalService it deleted *almost* everything (same thing happens when I run it under both of the said accounts).

I'm going to try building a simple program that just attempts to delete a specified directory -- perhaps it's some sort of issue with using a DLL (unlikely, but I'm kind of grabbing at straws here :)).

Thanks for your reply, by the way!

Edit: The barebones program throws the same exception (running as administrator). How odd. It's so weird how it's deleting some of the files and directories, but not all of them. I really don't get it.

Edit²: I just double-checked the ServiceProcessInstaller component in the service executable. The application is running as LocalSystem, so it shouldn't be a permissions issue even in that case.
 
I think I've isolated the problem. Windows doesn't appear to like to willingly delete read-only files, even through the kernel functions (hurray for old DOS features that don't seem to want to go away despite the fact that ACLs are far superior in every way :mad: ).

I'll edit this post as I figure things out.

Edit: Bingo! Setting the attributes fixed the problem. I'll post a snippet of the deletion code after I do another run of testing and clean it up some.

Edit²: Here's the working chunk of code:

VB.NET:
    Private Sub DeleteProfile(ByVal path As String)
        Try
            If Not pretend Then
                DebugOut("Deleting " + path)

                'since the read-only attribute causes the deletion to screw up, do that first
                SetAttributes(path)
                My.Computer.FileSystem.DeleteDirectory(path, FileIO.DeleteDirectoryOption.DeleteAllContents)
            Else
                DebugOut("Not really deleting " + path)
            End If
        Catch ex As Exception
            DebugOut("Could not delete directory: " + path + vbNewLine + "{exception: " + ex.ToString + "}")
        End Try
    End Sub

    Private Sub SetAttributes(ByVal directory As String)
        For Each fileName As String In My.Computer.FileSystem.GetFiles(directory)
            Try
                'set the file attributes to ensure that we can delete the file
                My.Computer.FileSystem.GetFileInfo(fileName).Attributes = FileAttributes.Normal
            Catch ex As Exception
                DebugOut("Could not set attributes on file: " + fileName)
            End Try
        Next

        For Each dirName As String In My.Computer.FileSystem.GetDirectories(directory)
            Try
                'set the file attributes to ensure that we can delete the directory
                My.Computer.FileSystem.GetFileInfo(dirName).Attributes = FileAttributes.Directory
            Catch ex As Exception
                DebugOut("Could not set attributes on directory: " + dirName)
            End Try

            'run through method recursively so that all files and directories are taken care of
            SetAttributes(dirName)
        Next
    End Sub
If anyone needs this for anything, DebugOut() points to my own debugging function, so those lines can be easily taken out. If you want to use it on .NET 1.0/1.1, you should be able to just replace the My.Computer.FileSystem with, uh, whatever they have that returns a string array of files and directories (it's been too long since I've used VS2003 :p ).

Hope this helps someone!
 
Last edited:
Back
Top