locked
Excluding (or if not removing specific folders) from Dim dirs() As String = Directory.GetDirectories(path) RRS feed

  • Question

  • Hi

    I am using 

      Dim dirs() As String = Directory.GetDirectories(path)

    To get list of folders from my drive

    I want to exclude all folders starting with $ e.g. $Recycle.Bin etc

    What is best way to either exclude them at point of retrieving them, or if that can't be done with GetDirectories (which I think it can't as filter can only include not exclude), then how can I remove them from dirs() before continuing with my code/

    Thanks


    Darren Rose

    Friday, November 20, 2020 7:15 PM

Answers

  • Hi

    Try a version of this (edit to suit etc)

    Dim excluded As Char = "$"c
    
    Dim dirs = IO.Directory.GetDirectories(path).Where(Function(s) Not s.Contains(excluded)).ToArray()
    


    Regards Les, Livingston, Scotland

    • Marked as answer by wingers Friday, November 20, 2020 8:06 PM
    Friday, November 20, 2020 7:53 PM
  • Although you have a solution, consider a more drawn out solution with events. It does lack async which will keep the app responsive.

    Imports System.IO
    
    Public Class Operations
    
        Public Delegate Sub OnTraverseFolder(status As String)
        Public Shared Event OnTraverseEvent As OnTraverseFolder
    
        Public Delegate Sub OnTraverseExcludeFolder(sender As String)
        Public Shared Event OnTraverseExcludeFolderEvent As OnTraverseExcludeFolder
    
    
        Public Shared Sub RecursiveFolders(baseDir As DirectoryInfo, exclude As String())
    
            If Not baseDir.Exists Then
                RaiseEvent OnTraverseEvent("Nothing to process")
                Return
            End If
    
            If Not exclude.Any(AddressOf baseDir.FullName.Contains) Then
                RaiseEvent OnTraverseEvent(baseDir.FullName)
            Else
                RaiseEvent OnTraverseExcludeFolderEvent(baseDir.FullName)
            End If
    
    
            For Each dir As DirectoryInfo In baseDir.EnumerateDirectories()
                Try
                    RecursiveFolders(dir, exclude)
                Catch ex As Exception
                    RaiseEvent OnExceptionEvent(ex)
                End Try
            Next
        End Sub
    
    End Class
    

    Form code

    Imports System.IO
    
    Public Class Form1
        Private Sub TraverseButton_Click(sender As Object, e As EventArgs) Handles TraverseButton.Click
            ListBox1.Items.Clear()
            Dim exclude = New String() {"obj", "bin"}
            Operations.RecursiveFolders(New DirectoryInfo("Some path"), exclude)
        End Sub
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            AddHandler Operations.OnTraverseEvent, AddressOf Traversing
            AddHandler Operations.OnTraverseExcludeFolderEvent, AddressOf ExcludeTraverse
            AddHandler Operations.OnExceptionEvent, AddressOf ExceptionHappened
        End Sub
    
        Private Sub ExceptionHappened(exception As Exception)
            Console.WriteLine($"{exception.Message,-20}")
        End Sub
    
        Private Sub ExcludeTraverse(sender As String)
            ListBox1.Items.Add(sender)
            ListBox1.SelectedIndex = ListBox1.Items.Count - 1
        End Sub
    
        Private Sub Traversing(sender As String)
            Console.WriteLine(sender)
        End Sub
    End Class
    


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    My GitHub code samples
    GitHub page

    • Proposed as answer by KHURRAM RAHIM Friday, November 20, 2020 8:54 PM
    • Marked as answer by wingers Friday, November 20, 2020 8:56 PM
    Friday, November 20, 2020 8:26 PM
  • P.S. Async would be handy, especially when enumerating large drives / folders

    Darren Rose

    Exactly but it took a little coding to get it done.

    Code resides in here, make sure to read the readme file which indicates the class project which is in the same GitHub repository under notes in the readme file.

    Note the layout is to demo using events to monitor operations in regards to ListBoxes. 


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    My GitHub code samples
    GitHub page

    • Marked as answer by wingers Sunday, November 22, 2020 8:22 PM
    Friday, November 20, 2020 9:39 PM
  • Hi Darren,

    I updated the code, all is responsive and reports issues with denied access to folders.

    Note I added an NuGet package BetterFolderBrowser which is optional for allowing a user to select a folder.


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    My GitHub code samples
    GitHub page

    • Marked as answer by wingers Saturday, November 21, 2020 12:41 PM
    Saturday, November 21, 2020 12:21 PM

All replies

  • Hi

    Try a version of this (edit to suit etc)

    Dim excluded As Char = "$"c
    
    Dim dirs = IO.Directory.GetDirectories(path).Where(Function(s) Not s.Contains(excluded)).ToArray()
    


    Regards Les, Livingston, Scotland

    • Marked as answer by wingers Friday, November 20, 2020 8:06 PM
    Friday, November 20, 2020 7:53 PM
  • Hi

    Try a version of this (edit to suit etc)

    Dim excluded As Char = "$"c
    
    Dim dirs = IO.Directory.GetDirectories(path).Where(Function(s) Not s.Contains(excluded)).ToArray()


    Regards Les, Livingston, Scotland

    That was so much easier than I had expected - thank you Les :)

    Darren Rose

    Friday, November 20, 2020 8:06 PM
  • Although you have a solution, consider a more drawn out solution with events. It does lack async which will keep the app responsive.

    Imports System.IO
    
    Public Class Operations
    
        Public Delegate Sub OnTraverseFolder(status As String)
        Public Shared Event OnTraverseEvent As OnTraverseFolder
    
        Public Delegate Sub OnTraverseExcludeFolder(sender As String)
        Public Shared Event OnTraverseExcludeFolderEvent As OnTraverseExcludeFolder
    
    
        Public Shared Sub RecursiveFolders(baseDir As DirectoryInfo, exclude As String())
    
            If Not baseDir.Exists Then
                RaiseEvent OnTraverseEvent("Nothing to process")
                Return
            End If
    
            If Not exclude.Any(AddressOf baseDir.FullName.Contains) Then
                RaiseEvent OnTraverseEvent(baseDir.FullName)
            Else
                RaiseEvent OnTraverseExcludeFolderEvent(baseDir.FullName)
            End If
    
    
            For Each dir As DirectoryInfo In baseDir.EnumerateDirectories()
                Try
                    RecursiveFolders(dir, exclude)
                Catch ex As Exception
                    RaiseEvent OnExceptionEvent(ex)
                End Try
            Next
        End Sub
    
    End Class
    

    Form code

    Imports System.IO
    
    Public Class Form1
        Private Sub TraverseButton_Click(sender As Object, e As EventArgs) Handles TraverseButton.Click
            ListBox1.Items.Clear()
            Dim exclude = New String() {"obj", "bin"}
            Operations.RecursiveFolders(New DirectoryInfo("Some path"), exclude)
        End Sub
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            AddHandler Operations.OnTraverseEvent, AddressOf Traversing
            AddHandler Operations.OnTraverseExcludeFolderEvent, AddressOf ExcludeTraverse
            AddHandler Operations.OnExceptionEvent, AddressOf ExceptionHappened
        End Sub
    
        Private Sub ExceptionHappened(exception As Exception)
            Console.WriteLine($"{exception.Message,-20}")
        End Sub
    
        Private Sub ExcludeTraverse(sender As String)
            ListBox1.Items.Add(sender)
            ListBox1.SelectedIndex = ListBox1.Items.Count - 1
        End Sub
    
        Private Sub Traversing(sender As String)
            Console.WriteLine(sender)
        End Sub
    End Class
    


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    My GitHub code samples
    GitHub page

    • Proposed as answer by KHURRAM RAHIM Friday, November 20, 2020 8:54 PM
    • Marked as answer by wingers Friday, November 20, 2020 8:56 PM
    Friday, November 20, 2020 8:26 PM
  • Thanks Karen

    Darren Rose

    Friday, November 20, 2020 8:41 PM
  • P.S. Async would be handy, especially when enumerating large drives / folders

    Darren Rose

    Friday, November 20, 2020 9:05 PM
  • P.S. Async would be handy, especially when enumerating large drives / folders

    Darren Rose

    Exactly but it took a little coding to get it done.

    Code resides in here, make sure to read the readme file which indicates the class project which is in the same GitHub repository under notes in the readme file.

    Note the layout is to demo using events to monitor operations in regards to ListBoxes. 


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    My GitHub code samples
    GitHub page

    • Marked as answer by wingers Sunday, November 22, 2020 8:22 PM
    Friday, November 20, 2020 9:39 PM
  • Thank you Karen, will take a look now

    Darren Rose


    • Edited by wingers Friday, November 20, 2020 10:05 PM
    Friday, November 20, 2020 9:56 PM
  • Its going to need some error handling I think, as first test on my C:\ drive (even when running it as admin) I get 

    System.UnauthorizedAccessException: 'Access to the path 'C:\Documents and Settings' is denied.' on line 73 of Operations.vb


    Darren Rose

    Friday, November 20, 2020 10:05 PM
  • Its going to need some error handling I think, as first test on my C:\ drive (even when running it as admin) I get 

    System.UnauthorizedAccessException: 'Access to the path 'C:\Documents and Settings' is denied.' on line 73 of Operations.vb


    Darren Rose

    Hi

    Yes, there are many exception traps when trying to access protected locations/files etc. Some are a real bother to try and deal with. A normal Try....Catch block is commonly of no use at all in some circumstances.  Another trap are those items that are not true dirctories but are pointers to the actual directory (has a name but I can't remember) - such as My Music, My Pictures, My Videos and maybe some othersThe access denied can sometimes be dealt with but other times it seems near impossible to deal with (at least at my level of competence).


    Regards Les, Livingston, Scotland

    Friday, November 20, 2020 10:11 PM
  • @leshay

    Agreed, it can be a real pain.  I think they are referred to as reparse points or junctions


    Darren Rose

    Friday, November 20, 2020 10:27 PM
  • Its going to need some error handling I think, as first test on my C:\ drive (even when running it as admin) I get 

    System.UnauthorizedAccessException: 'Access to the path 'C:\Documents and Settings' is denied.' on line 73 of Operations.vb


    Darren Rose

    If you are talking about Operations from my code, you can rearrange the try catch if EnumerateDirecotries is throwing the error. I did this rather fast and know there can be issues with permissions. Personally I tend to use a tool called FileLocator Pro and that even has an API to use in C# (should not be difficult to use for vb).

    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    My GitHub code samples
    GitHub page

    Saturday, November 21, 2020 12:00 AM
  • Yes the error was thrown in Operations.vb - part of your FileHelpers project in Public Shared Async Sub RecursiveFolders 

    I will have a play and see what I can change with the try..catch

    Had a quick look at FileLocator Pro and they do VB API as well, but its not cheap!



    Darren Rose

    Saturday, November 21, 2020 12:07 AM
  • Think it is now working

    In Operations.vb

    Change

     For Each dir As DirectoryInfo In baseDir.EnumerateDirectories()
                Try
    
                    Dim folder = dir
    
                    If Not Cancelled Then
    
                        Await Task.Run(Async Function()
                                           Await Task.Delay(10)
                                           RecursiveFolders(folder, exclude, ct)
                                       End Function)
                    Else
                        Return
                    End If
    
    
                    If ct.IsCancellationRequested Then
                        ct.ThrowIfCancellationRequested()
                    End If
    
                Catch ex As Exception
                    '
                    ' Only raise exceptions, not cancellation request
                    '
                    If TypeOf ex Is OperationCanceledException Then
                        Cancelled = True
                    Else
                        RaiseEvent OnExceptionEvent(ex)
                    End If
    
                End Try
            Next

    to

    Try
                For Each dir As DirectoryInfo In baseDir.EnumerateDirectories()
    
    
                    Dim folder = dir
    
                    If Not Cancelled Then
    
                        Await Task.Run(Async Function()
                                           Await Task.Delay(10)
                                           RecursiveFolders(folder, exclude, ct)
                                       End Function)
                    Else
                        Return
                    End If
    
    
                    If ct.IsCancellationRequested Then
                        ct.ThrowIfCancellationRequested()
                    End If
    
                Next
    
            Catch ex As Exception
                '
                ' Only raise exceptions, not cancellation request
                '
                If TypeOf ex Is OperationCanceledException Then
                    Cancelled = True
                Else
                    RaiseEvent OnExceptionEvent(ex)
                End If
    
    
            End Try


    Darren Rose

    Saturday, November 21, 2020 12:10 AM
  • The above fixes the crashing issue, but the cancel button doesn't work as despite appearing to work the form is unresponsive to clicks etc

    Loving the idea so any input you can give would be much appreciated

    Thank you


    Darren Rose

    Saturday, November 21, 2020 12:12 AM
  • Hi Darren,

    I updated the code, all is responsive and reports issues with denied access to folders.

    Note I added an NuGet package BetterFolderBrowser which is optional for allowing a user to select a folder.


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    My GitHub code samples
    GitHub page

    • Marked as answer by wingers Saturday, November 21, 2020 12:41 PM
    Saturday, November 21, 2020 12:21 PM
  • Thank you Karen, that works perfectly! some really useful bits in your GitHub project, great work and thanks for sharing

    Darren Rose

    Saturday, November 21, 2020 12:41 PM
  • P.S. I also need to traverse files separately, I assume I can just rework and replace dir with file, DirectoryInfo with FileInfo and EnumerateDirectories with EnumerateFiles etc?  or is there a better way to do it, so basically I can end up with list of dirs in one variable and files in another

    Thanks again


    Darren Rose

    Saturday, November 21, 2020 12:49 PM
  • P.S. I also need to traverse files separately, I assume I can just rework and replace dir with file, DirectoryInfo with FileInfo and EnumerateDirectories with EnumerateFiles etc?  or is there a better way to do it, so basically I can end up with list of dirs in one variable and files in another

    Thanks again


    Darren Rose

    Not knowing you would ask for this I happened to code a basic code sample in the same project. All code currently in the form as I'm heading out for the day. The path is hard coded to C:\Users searching for *.dll.

    Form code


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    My GitHub code samples
    GitHub page

    Saturday, November 21, 2020 2:15 PM