Link to home
Start Free TrialLog in
Avatar of psyfect
psyfect

asked on

VB.Net Recurse Subdirectories (permissions?)

I am attempting to identify all subdirectories within a user-specified path on two Operating Systems, Vista and XP.  I have two current options.  The first one seems to be the best, as it tends to actually read the folders, my problem is that it is broken somehow, and not truly recursive:

    Public Function SearchFolders(ByVal path As String) As Long
        Dim Dir As New IO.DirectoryInfo(path)
        Dim Fils As IO.DirectoryInfo() = Dir.GetDirectories()
        Dim Fil As IO.DirectoryInfo

        For Each Fil In Fils
            MsgBox(Fil.Name)
            SearchFolders(Fil.FullName & "\")
        Next
    End Function

Preferably, I would like to have a functioning version of this code which actually acknowledges all subdirectories.  Alternatively, however, I found different code which seems to work flawlessly and is extremely small.  The problem, although, appears to be permissions.

The previous code will acknowledge paths below "C:\Users\" on a Vista machine (at least the ones found by the broken code).  The following code, however, seems to not have permissions and consequently does not display anything:

    Public Function RecursiveFolder(ByVal path As String) As Long
        For Each fold As String In My.Computer.FileSystem.GetDirectories(path, FileIO.SearchOption.SearchAllSubDirectories)
            MsgBox(fold)
        Next
    End

If I were to use the above code on a path to an external hard drive, all subdirectories would be acknowledged.  Though if I were to chose "C:\Users\" on Vista I get nothing.  So while this code would be most efficient for an XP machine with no preset permissions, it is useless for my requirements.
Avatar of graye
graye
Flag of United States of America image

That's correct, the built-in SearchAllSubDirectories doesn't have a way to "detect error and continue".   So, when it hits the first error, it bails completely.
So, that just means you'll need to use you're first approach... with a tiny modification to include the "detect and continue" feature.
The following is an example from one of my programs (so ignore the parts that are not relevant)
BTW:  The .Net Framework doesn't have a way to traverse a directory path that greater than 260 characters long.   If that's also a problem  you run accross, I've got replacement set of System.IO classes that will fix that.

Imports System.IO
 
Public Class Traverse
 
    Private first As Boolean
    Private f_count, d_count As Integer
 
    Public ReadOnly Property FileCount() As Integer
        Get
            Return f_count
        End Get
    End Property
 
    Public ReadOnly Property DirectoryCount() As Integer
        Get
            Return d_count
        End Get
    End Property
 
    Public Sub Doit(ByVal StartingDir As String)
        Dim p_di, di, di_array() As DirectoryInfo
        Dim fi, fi_array() As FileInfo
 
        ' dress it up a wee bit...
        If Not StartingDir.EndsWith("\") Then
            StartingDir = StartingDir & "\"
        End If
 
        ' skip the recycle bin and other directories we don't care about...
        For Each skip As String In My.Settings.SkipList
            If StartingDir.EndsWith(skip, StringComparison.CurrentCultureIgnoreCase) Then
                Exit Sub
            End If
        Next
 
        Try
            p_di = New DirectoryInfo(StartingDir)
        Catch
            ' silently ignore these errors
            Exit Sub
        End Try
 
        ' get the starting directory info (first run only)
        If first Then
            Try
                Debug.WriteLine("Dir: " & StartingDir)
                first = False
                d_count += 1
            Catch ex As Exception
                Debug.WriteLine("Error: " & ex.Message)
                ' not fatal
            End Try
        End If
 
        ' process files first
        Try
            fi_array = p_di.GetFiles
        Catch ex As Exception
            Debug.WriteLine("Error: " & ex.Message)
            Exit Sub
        End Try
 
        For Each fi In fi_array
            Try
                Debug.WriteLine("File: " & fi.FullName)
                f_count += 1
            Catch ex As Exception
                Debug.WriteLine("Error: " & ex.Message)
                ' not fatal
            End Try
        Next
 
        ' Process the directories (and descend into dir structure)
        Try
            di_array = p_di.GetDirectories
        Catch ex As Exception
            ' This probably redundant, since we catch this type of
            ' error above while processing files.
            Debug.WriteLine("Error: " & ex.Message)
            Exit Sub
        End Try
 
        For Each di In di_array
            Try
                Debug.WriteLine("Dir: " & di.FullName)
                d_count += 1
            Catch ex As Exception
                Debug.WriteLine("Error: " & ex.Message)
                ' not fatal
            End Try
 
            ' recursive call to this subroutine
            Doit(di.FullName)
        Next
    End Sub
 
End Class

Open in new window

Avatar of psyfect
psyfect

ASKER

So I was looking at your code there and noticed the following (edited):
        For Each di In di_array
            ' recursive call to this subroutine
            Doit(di.FullName)
        Next

I don't see much difference in that code from my original:
    Public Function SearchFolders(ByVal path As String) As Long
        Dim Dir As New IO.DirectoryInfo(path)
        Dim Fils As IO.DirectoryInfo() = Dir.GetDirectories()
        Dim Fil As IO.DirectoryInfo

        For Each Fil In Fils
            MsgBox(Fil.Name)
            SearchFolders(Fil.FullName & "\")
        Next
    End Function

The problem though is that it doesn't appear to be recursive.  Am I doing something wrong or do you think I'm encountering an error and it's just stopping on me?
Avatar of psyfect

ASKER

I tried adding an error catch and no error messages arose.  It appears my code is simply not properly formated for recursion:
    Public Function SearchFolders(ByVal path As String) As Long
        Dim Dir As New IO.DirectoryInfo(path)
        Dim Fils As IO.DirectoryInfo() = Dir.GetDirectories()
        Dim Fil As IO.DirectoryInfo
        Dim d_count As Long

        For Each Fil In Fils
            Try
                MsgBox("Dir: " & Fil.FullName)
                d_count += 1
            Catch ex As Exception
                MsgBox("Error: " & ex.Message)
                ' not fatal
            End Try
            MsgBox(Fil.Name)
            SearchFolders(Fil.FullName)
        Next
    End Function
Avatar of psyfect

ASKER

Oh no.  It does appear to work fine.  I tried it on my D:\ drive and it works fine...why can I browse the first few folders in C:\Users\ on Vista, but not the rest?  That doesn't really make any sense.  It is imperitive that I can scan all user folders.  How can I easily incorporate this functionality?

I remember there were no issues with VB6 code, I just don't remember that code (I think it was API calls).
Avatar of psyfect

ASKER

So here's a summary, on vista my program will browse C:\Users all the way to "C:\Users\Administrator\AppData\Local\application data" (4 folders deep).  Now if I type that folder into my explorer it says access denied.  Why is it that the program actually sees a folder that I can't manually browse to and more importantly why does it stop there?  How do I force the program to continue?
So, what if I was to tell you that the sample that I posted, doesn't suffer from that problem... and that it will continue to list all files and directories even after it encounters an error
Here is an entire application based upon the principles in that example: http://home.hot.rr.com/graye/Temp/FS_Dump.zip
 
Avatar of psyfect

ASKER

I would have to say that I thought I tried your variation on the code to no avial.  Perhaps I overlooked something?  I'll have to check out the application later this evening if possible.  Thanks for your help thus far!
Avatar of psyfect

ASKER

I downloaded the code and inspected it.  I found no differences in my code other than the absence of this call: System.Security.Principal.SecurityIdentifier.  Is this something I should be including to allow access?  I'm sorry if I'm missing something obvious.  I've even tried running my program as administrator.  It works flawlessly on xp and not at all on Vista =/
Avatar of psyfect

ASKER

There has got to be a simple solution to this.  What if I simply wanted to create a program that deletes one file in my user directory on Vista in vb.net?  Isn't there a simple solution to have the program prompt for rights or something?
Yeah, but did the FS_Dump application work as I described?  
If so, then it should be rather easy to discover where your application is different
No, System.Security.Principal.SecurityIdentifier has nothing to do with this
ASKER CERTIFIED SOLUTION
Avatar of psyfect
psyfect

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial