# VBForums CodeBank > CodeBank - Visual Basic .NET >  VB.Net: Recursive File Searching...

## <ABX

VB Code:
Option Strict On
Option Explicit On 
 Imports System.IO
     Public Class FileSearch
         Private Const DefaultFileMask As String = "*.*"
        Private Const DefaultDirectoryMask As String = "*"
 #Region " Member Variables "
         Private _InitialDirectory As DirectoryInfo
        Private _DirectoryMask As String
        Private _FileMask As String
         '
        Private _Directories As New ArrayList
        Private _Files As New ArrayList
 #End Region
 #Region " Properites "
         Public Property InitialDirectory() As DirectoryInfo
            Get
                Return _InitialDirectory
            End Get
            Set(ByVal Value As DirectoryInfo)
                _InitialDirectory = Value
            End Set
        End Property
        Public Property DirectoryMask() As String
            Get
                Return _DirectoryMask
            End Get
            Set(ByVal Value As String)
                _DirectoryMask = Value
            End Set
        End Property
        Public Property FileMask() As String
            Get
                Return _FileMask
            End Get
            Set(ByVal Value As String)
                _FileMask = Value
            End Set
        End Property
         Public ReadOnly Property Directories() As ArrayList
            Get
                Return _Directories
            End Get
        End Property
        Public ReadOnly Property Files() As ArrayList
            Get
                Return _Files
            End Get
        End Property
   #End Region
 #Region " Constructors "
         Public Sub New()
         End Sub
         Public Sub New( _
            ByVal BaseDirectory As String, _
            Optional ByVal FileMask As String = DefaultFileMask, _
            Optional ByVal DirectoryMask As String = DefaultDirectoryMask)
             Me.New(New IO.DirectoryInfo(BaseDirectory), FileMask, DirectoryMask)
         End Sub
         Public Sub New( _
            ByVal BaseDirectory As DirectoryInfo, _
            Optional ByVal FileMask As String = DefaultFileMask, _
            Optional ByVal DirectoryMask As String = DefaultDirectoryMask)
             _InitialDirectory = BaseDirectory
            _FileMask = FileMask
            _DirectoryMask = DirectoryMask
         End Sub
 #End Region
         Protected Overrides Sub Finalize()
            _Files = Nothing
            _Directories = Nothing
            MyBase.Finalize()
        End Sub
          Public Sub Search( _
            Optional ByVal BaseDirectory As DirectoryInfo = Nothing, _
            Optional ByVal FileMask As String = Nothing, _
            Optional ByVal DirectoryMask As String = Nothing)
             If Not IsNothing(BaseDirectory) Then
                _InitialDirectory = BaseDirectory
            End If
             If IsNothing(_InitialDirectory) Then
                Throw New ArgumentException("A Directory Must be specified!", "Directory")
            End If
             If IsNothing(FileMask) Then
                _FileMask = DefaultFileMask
            Else
                _FileMask = FileMask
            End If
              If IsNothing(DirectoryMask) Then
                _DirectoryMask = DefaultDirectoryMask
            Else
                _DirectoryMask = DirectoryMask
            End If
             DoSearch(_InitialDirectory)
        End Sub
         Private Sub DoSearch(ByVal BaseDirectory As DirectoryInfo)
             Try
                _Files.AddRange(BaseDirectory.GetFiles(_FileMask))
            Catch u As UnauthorizedAccessException
                'Siliently Ignore this error, there isnt any simple
                'way to avoid this error.
             End Try
             Try
                Dim Directories() As DirectoryInfo = BaseDirectory.GetDirectories(_DirectoryMask)
                _Directories.AddRange(Directories)
                 For Each di As DirectoryInfo In Directories
                    DoSearch(di)
                Next
             Catch u As UnauthorizedAccessException
                'Siliently Ignore this error, there isnt any simple
                'way to avoid this error.
             End Try
         End Sub
     End Class

Usage:


VB Code:
Dim x As New FileSearch(New IO.DirectoryInfo("d:\Media\"), "*.nfo")
         x.Search()
         MessageBox.Show(x.Files.Count) ' number of files that match "*.nfo" in D:\Media
        MessageBox.Show(x.Directories.Count) ' the total number of directories looked through

Edit: Now with MessageBox.Show   :Stick Out Tongue: 
Edit Again: Fixed some minor bugs, Masks were being overrided by Optional Parameters (duh), Added overload of the constructor, added some try... catch blocks to skip any directories/files that the user doesnt have access to.

(It was buggy because I striped this out of a custom library (orginally, this was threaded)

----------


## wossname

You might want to change the variable name "Directory" to something else.  It conflicts with IO.Directory.   :Smilie:

----------


## dglienna

What is the *xous.Common.* in the code.  It worked without it.


VB Code:
Dim x As New xous.Common.FileSearch(New IO.DirectoryInfo("d:\Media\"), "*.nfo")

----------


## <ABX

> What is the *xous.Common.* in the code.  It worked without it.
> 
> 
> VB Code:
> Dim x As New xous.Common.FileSearch(New IO.DirectoryInfo("d:\Media\"), "*.nfo")


heh... I ripped this code out of a library of mine... I removed the Namespace on the class but I guess I was still thinking it was there when I wrote the example.

----------


## bfackrell

I was referred to your code from somebody on an other board and it has been an absolute life saver for me.

Can you tell me if there is a simple change/addition that can be made that will allow this search app to also search the subfolders of the selected folder?

Thanks
Brad

----------


## bfackrell

> I was referred to your code from somebody on an other board and it has been an absolute life saver for me.
> 
> Can you tell me if there is a simple change/addition that can be made that will allow this search app to also search the subfolders of the selected folder?
> 
> Thanks
> Brad


Sorry...I see that it does search subdirectories.

Thanks agian.

----------


## quacka

I want to use this to search for images. how can i alter this so it wil accept more then one file mask when it search?

Thanks

----------


## <ABX

I would modify it like this:


VB Code:
Option Strict On
Option Explicit On 
 Imports System.IO
Imports System.Collections.Specialized
 Public Class FileSearch
     Private Const DefaultFileMask As String = "*.*"
    Private Const DefaultDirectoryMask As String = "*"
 #Region " Member Variables "
     Private _InitialDirectory As DirectoryInfo
    Private _DirectoryMasks As StringCollection
    Private _FileMasks As StringCollection
     '
    Private _Directories As New ArrayList
    Private _Files As New ArrayList
 #End Region
 #Region " Properites "
     Public Property InitialDirectory() As DirectoryInfo
        Get
            Return _InitialDirectory
        End Get
        Set(ByVal Value As DirectoryInfo)
            _InitialDirectory = Value
        End Set
    End Property
    Public Property DirectoryMask() As StringCollection
        Get
            Return _DirectoryMasks
        End Get
        Set(ByVal Value As StringCollection)
            _DirectoryMasks = Value
        End Set
    End Property
    Public Property FileMask() As StringCollection
        Get
            Return _FileMasks
        End Get
        Set(ByVal Value As StringCollection)
            _FileMasks = Value
        End Set
    End Property
     Public ReadOnly Property Directories() As ArrayList
        Get
            Return _Directories
        End Get
    End Property
    Public ReadOnly Property Files() As ArrayList
        Get
            Return _Files
        End Get
    End Property
 #End Region
 #Region " Constructors "
     Public Sub New()
     End Sub
     Public Sub New( _
        ByVal BaseDirectory As String)
        Me.New(New DirectoryInfo(BaseDirectory))
    End Sub
     Public Sub New( _
        ByVal InitialDirectory As DirectoryInfo)
         _InitialDirectory = InitialDirectory
    End Sub
 #End Region
     Public Overloads Sub Search(ByVal InitalDirectory As String, _
        Optional ByVal FileMask As String = Nothing, _
        Optional ByVal DirectoryMask As String = Nothing)
         Search( _
            New DirectoryInfo(InitalDirectory), _
            FileMask, _
            DirectoryMask _
            )
     End Sub
        Public Overloads Sub Search( _
        Optional ByVal InitalDirectory As DirectoryInfo = Nothing, _
        Optional ByVal FileMask As String = Nothing, _
        Optional ByVal DirectoryMask As String = Nothing)
         _Files = New ArrayList
        _Directories = New ArrayList
         If Not IsNothing(InitalDirectory) Then
            _InitialDirectory = InitalDirectory
        End If
         If IsNothing(_InitialDirectory) Then
            Throw New ArgumentException("A Directory Must be specified!", "Directory")
        End If
         If IsNothing(FileMask) OrElse FileMask.Length = 0 Then
            _FileMasks = New StringCollection
            _FileMasks.Add(DefaultFileMask)
        Else
            _FileMasks = ParseMask(FileMask)
        End If
         If IsNothing(DirectoryMask) OrElse DirectoryMask.Length > 0 Then
            _DirectoryMasks = New StringCollection
            _DirectoryMasks.Add(DefaultDirectoryMask)
        Else
            _DirectoryMasks = ParseMask(DirectoryMask)
        End If
         DoSearch(_InitialDirectory)
    End Sub
     Private Sub DoSearch(ByVal BaseDirectory As DirectoryInfo)
         Try
            For Each fm As String In _FileMasks
                Files.AddRange(BaseDirectory.GetFiles(fm))
            Next
            _
        Catch u As UnauthorizedAccessException
            'Siliently Ignore this error, there isnt any simple
            'way to avoid this error.
         End Try
         Try
            Dim Directories As New ArrayList
             For Each dm As String In _DirectoryMasks
                Directories.AddRange(BaseDirectory.GetDirectories(dm))
                _Directories.AddRange(Directories)
            Next
             For Each di As DirectoryInfo In Directories
                DoSearch(di)
            Next
         Catch u As UnauthorizedAccessException
            'Siliently Ignore this error, there isnt any simple
            'way to avoid this error.
         End Try
     End Sub
     'Masks are formated like *.jpeg;*.jpg
    Private Shared Function ParseMask(ByVal Mask As String) As StringCollection
        If IsNothing(Mask) Then
            Return Nothing
        End If
        Mask = Mask.Trim(";"c)
        If Mask.Length = 0 Then
            Return Nothing
        End If
        Dim Masks As New StringCollection
         Masks.AddRange(Mask.Split(";"c))
         Return Masks
    End Function
      Protected Overrides Sub Finalize()
        _Files = Nothing
        _Directories = Nothing
        MyBase.Finalize()
    End Sub
 End Class

Sample Usage:


VB Code:
Dim x As New FileSearch()
         x.Search("d:\Media\", "*.jpg;*.jpeg")
         MessageBox.Show(x.Files.Count) ' number of files that match "*.jpg" and "*.jpeg" in D:\Media\Pictures
        MessageBox.Show(x.Directories.Count) ' the total number of directories looked through

----------


## quacka

Thanks for that.

I tried it and go this error message
An unhandled exception of type 'System.NullReferenceException' occurred in Send To DLAB.exe

Additional information: Object reference not set to an instance of an object.

at line: 
Mask = Mask.Trim(";"c)

----------


## <ABX

Argh... Fixed.

Removed the Optional Parameters from the constructor and modified it so a more than one search can be preformed on an Instance.

----------


## alehawk

Hi!
This is an excelent function!
Is there anyway I can get the full path to the files found?
I tryed and tryed but I couldnt get it, I could get the current directory for the file but no the full path to the file.
If anyone knows how to do it pleas lend me a hand.
Thank you very much.

----------


## quacka

The function returns an arraylist of fileinfo
you can get the fullpath by :

x.Search(selectedPath, "*.jpg;*.jpeg;*.tif;*.tiff")
For Each imageFiles As FileInfo In x.Files
        Dim img = Image.FromFile(imageFiles.FullName)
                    If img.PhysicalDimension.width < minWIdth Or img.PhysicalDimension.height < minHeight Then
                        arAutoImageNotOK.Add(imageFiles)
                    Else
                        arAutoImageOK.Add(imageFiles)
                    End If
                    img = Nothing
next


This is just an example because I use it to check the dimension of the images which I used x to search for.

----------


## alehawk

Thank you for the reply but I use this class for general search not only of images.
Can the full path be retreived if its not an image?
Tnx!

----------


## quacka

Yes,

It is an arraylist of fileinfo. so you will need to use for each statement to retrieve each element of the array. then use the element.fullname to get the full path

----------


## alehawk

ahhhhhhhhhhh ok, it my first time using an arraylist in net, i'll try it!
Thank you very much!!

----------


## quacka

anytime

----------


## singletrail

Hi there, ...great code,... but is there the possiblity to add multithreading to it so in GUI's users can work without having to wait for search-results?

----------


## Kasracer

> Hi there, ...great code,... but is there the possiblity to add multithreading to it so in GUI's users can work without having to wait for search-results?


Just add it yourself. That way you can control GUI updating

----------


## Rossonero

First off, Hi!
Second, super code dude. 
And so... I want to add the search result to a listbox called ListBox1  :Big Grin:  
How?

This is what I've tried but it does not work.  :Confused:  
 Dim x As New FileSearch()
        x.Search("e:\mp3\", "*.mp3")
        ListBox1.Items.Add(x)

The listbox gets just one line which says:
"WindowsApplication1.FileSearch"

Thanks

----------


## <ABX

Change your code to the following


VB Code:
'Creates an instance of FileSearch
Dim x As New FileSearch()
 'Preforms the Search
x.Search("e:\mp3\", "*.mp3")
 ' Takes the results of the search x.Files, which is an array list
' And converts it to an Array to allow it to be passed to the AddRange method
 ListBox1.Items.AddRange(x.Files.ToArray)

If you want to have the results formatted differently, you must add each item Individually.


VB Code:
' eg...
 For each f as System.IO.FileInfo in x.Files
    Listbox1.Items.Add(f.toString()) 
Next

----------


## Rossonero

Thanks man. That helped alot.   :Thumb:

----------


## mminto

Hi,
      I am developing a text search tool which gives the user the ability to open and scan a set of text based source files for a particular text string. This class looks like a great candidate for the Job. However, I would like to give the user the ability to scan various file types in either one parent directory, or the parent directory & all its child directories. 

      What is the correct usage of the class for finding files in just one directory, or a particular directory and all its child directories?

Thanks in advance.

----------


## ctbfalcon

> Yes,
> 
> It is an arraylist of fileinfo. so you will need to use for each statement to retrieve each element of the array. then use the element.fullname to get the full path


Can you give a sample for this.



```
        Dim i As Integer
        For i = 0 To x.Files.Count - 1
            Console.WriteLine(CStr(x.Files.Item(i)))
        Next
```

I tried that but its not working.

----------


## jwakeman

The class written by ABX is very well written but I if you are looking for a simpler solution as I was you may find this one-liner useful:



```
 Dim searchResults As String() = Directory.GetFiles(SOFTWARE_RELEASE_FOLDER, "*.tgz", SearchOption.AllDirectories)
```

where SOFTWARE_RELEASE_FOLDER is the base directory as a string, "*.tgz" is the file mask, and the third parameter tells the function to search recursively.

The return is an array of strings which are the full path to each identified file.

----------


## tearman

Hi 

     can i know how this one liner will be usefull to me? i mean i am a beginner in programming vb.net. i want to search a given file name and copy the file name in a specific folder. plz help me .


    thank you

----------


## jwakeman

This would search for files ending in .txt in c:\ and any subdirectories.  Then loops through the results and displays each in a message box.  That help?



```
Dim searchResults As String() = Directory.GetFiles("c:\", "*.txt", SearchOption.AllDirectories)

For each result as string in searchResults
messagebox.show(result)
next
```


You can use system.IO.File.Copy(sourceFile, destinationFile) to copy files.

----------


## tearman

Thanx jwakeman

----------


## tearman

hi jakeman 

thanx for the help. only now i tried ur tip. 
i couldnot get the word "searchoption" so how can i search all directories.
please help.

----------


## tearman

without the third parameter ie the searchoption, the code helps to search the files. but i want to search the subdirectories if it is not in the given source. i am using vb2003.
please help.

thanx

----------


## MXTECH

Hey man Awesome code! i have been looking for something like this for 6months!
i was wondering how could you get it to show the currently scanned file in a 
little text label or something, and how to stop the search button. i need it not
to frezz the program when searching too cos it shows the user nothing while it works untill you get a message with the things found.

i love the code and you rock dude!

Jared Woodruff

----------


## speedy6

I'm using this like:
x.Search(My.Computer.FileSystem.Drives.Item(0).ToString, "*.png;*.Gif;*.Jpg;*.Png;*.tif;*.jpeg", "Windows")
So I want to get all the picture but not at the folder windows.
But when I try this. I still get the picture from the folder Windows..and I cant figure out why...

----------


## <ABX

> The class written by ABX is very well written but I if you are looking for a simpler solution as I was you may find this one-liner useful:
> 
> 
> 
> ```
>  Dim searchResults As String() = Directory.GetFiles(SOFTWARE_RELEASE_FOLDER, "*.tgz", SearchOption.AllDirectories)
> ```
> 
> where SOFTWARE_RELEASE_FOLDER is the base directory as a string, "*.tgz" is the file mask, and the third parameter tells the function to search recursively.
> ...


The class I published above is deprecated in favor of the method mentioned above as Microsoft extended the Directory.GetFiles() method to include support for recursive file searching in the .Net Framework versions 3.5, 3.0, 2.0.

The above code should only be used in previous versions of the .Net framework or for a real world example on how and why to use recursion.




> Hey man Awesome code! i have been looking for something like this for 6months!
> i was wondering how could you get it to show the currently scanned file in a
> little text label or something, and how to stop the search button. i need it not
> to frezz the program when searching too cos it shows the user nothing while it works untill you get a message with the things found.
> 
> i love the code and you rock dude!
> 
> Jared Woodruff


This code is synchronous which means that it was not designed for the use you have in mind. You would need to pretty much rewrite the above code from scratch to make it asynchronous.

----------


## GetRich

Thanks! great code!
But how can i make it write the results into .txt file?
And that other guy asked about getting the full path, and i just dont get how to use it, Help please!
Sorry for my english..
Thanks again!

----------


## Rossonero

I'm no VB guru but I would do it like this.


```
Imports System.IO
Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim s As New FileSearch()
        Dim sw1 As New StreamWriter("test.txt", True)
        Dim sw2 As New StreamWriter("test2.txt", True)
        s.Search("c:\windows", "*.dll")

        For Each file As System.IO.FileInfo In s.Files
            sw1.WriteLine(file.ToString())
            sw2.WriteLine(file.FullName.ToString())
        Next
        End
    End Sub
End Class
```

This is with <ABX's modified version

----------


## GetRich

Thanks!!

----------


## vip_scarface_vip

Thank you alot 
Have Nice Day Cya  :wave:

----------


## sbasak

This is a great piece of code!

But can someone please tell me how to search for files in given directory only excluding any subdirectories under it?

Thanks

----------


## Rossonero

If you don't need to search subdirectories then this code will do just fine



```
        Dim filetype As String = "*.txt"
        Dim dir As String = "c:\windows"
        For Each filename As String In System.IO.Directory.GetFiles(dir, filetype)
            ListBox1.Items.Add(filename) 'Or do whatever with the result
        Next
```

----------


## bninja

Lol, I signed up just so I could help sbasak out but you already beat me to it  Rossonero  :Wink: 

..but now I'm wondering, how would one accomplish the same thing using ABX's modifications. That is,  not searching deeper then the directory specified ?

anyone know ?

----------


## sbasak

Yes, I was looking for a modification in original code.

In the original Search function, I tried putting a 3rd parameter for absurd directory name like "QQQQQ" to look for only those directories (thus skipping normal sub directories)  but it didn't work.  :Blush: 

eg. x.Search("F:\Windows", "*.doc;*.txt", "QQQZZZ")

Also System.IO.Directory.GetFiles(dir, filetype) can't search for multiple wildchars as in ABX's function.

GetFiles has a 3rd parameter which tells whether to search inside sub-directories as well. But it can't interpret multiple wildchars!

----------


## wjburke2

Did anyone ever get a "Could not find a part of the path 'C:\Documents and Settings\All Users\Start Menu\Programs\IBM Softcopy Reader'." I know the dir exists. Weird error, all my research references mapped drives not a local drive. Great code by the way 6 years and still used can't beat that.

----------


## dbasnett

Wouldn't it be appropriate to post code here using Code tags instead of VBCode tags?  I always find it difficult to copy / paste code posted with VBCode tags

----------


## vortexofhate

Love the code, it is great. I had a question though. If I wanted to exclude certain directories from being searched? Like C:\Program Files or C:\Windows? Might be a stupid question and I missed something simple. Any help would be greatly appreciated. Thanks.

----------

