A few times a month, I will see people asking in the forums how to search the hard drive for a file. In the past I would normally refer them to an old thread where I had provided a link to a file scan utility I had written. I got to thinking about it and I thought it was high time that I take that example and turn it into a re-usable class that could be easily integrated into someone else's search interface.
Please be aware that I will be providing a complete example project on how to use the 'DriveSearcher' class, but the interface only shows how to use the DriveSearcher class. I would also like to note that if you wish to see the comments for the code, that you will need to download the entire sample project from the MSDN Gallery, as this article is more of a supporting explanation for what the DriveSearcher does. You can download the sample project at the following link: DriveSearcher Sample Project Please be sure to vote 5 stars while you're there!
The drive searcher class automatically runs on its own thread. This means that your application will remain responsive while the drive searcher performs its search routines. When calling the DriveSearcher.SearchDrive Sub routine, you will notice that this routine is a shared routine. This means that you need not construct an instance of the DriveSearcher class. This class will create its own internal instances each time the DriveSearcher.SearchDrive method is called. We will get more into that later.
In order to search a drive, you need only call the DriveSearcher.SearchDrive sub routine. Before you are able to call that sub routine, you need to be able to pass the required parameter to the sub(ByVal params As SearchParamaters). What is the Object Type SearchParamters? This is a special class that was created to compliment the use of DriveSearcher. This object reduces the size of the parameter for the DriveSearcher.SearchDrive method. This object also contains all of the fields that are required to instantiate a search, and to handle the events of the search. Let us examine the SearchParamaters Class:
01.
Option
Strict
On
02.
Explicit
03.
Infer Off
04.
Public
Class
SearchParamaters
05.
Inherits
EventArgs
06.
Private
_DriveRootPath
As
String
07.
_FindFile
08.
_Invoker
Control
09.
FileFoundEventHandler
DriveSearcher.FileFoundEventHandler
10.
SearchStatusChangedEventhandler
DriveSearcher.StatusChangedEventHandler
11.
ReadOnly
Property
DriveRootPath
12.
Get
13.
Return
14.
End
15.
16.
FindFile
17.
18.
19.
20.
21.
Invoker
22.
23.
24.
25.
26.
Sub
New
(
ByVal
, _
27.
28.
Control, _
29.
Optional
DriveSearcher.FileFoundEventHandler =
Nothing
30.
DriveSearcher.StatusChangedEventHandler =
)
31.
If
GetDrives.IndexOf(DriveRootPath.ToLower) < 0
Then
32.
Throw
ArgumentException(
"The specified Drive Root Path is invalid."
,
"DriveRootPath"
33.
34.
Is
"You must specify an invoker."
"Invoker"
35.
Me
._DriveRootPath = DriveRootPath
36.
._FindFile = FindFile
37.
._Invoker = Invoker
38.
.FileFoundEventHandler = FileFoundEventHandler
39.
.SearchStatusChangedEventhandler = SearchStatusChangedEventhandler
40.
41.
Function
GetDrives()
List(Of
42.
Dim
drives
IO.DriveInfo() = IO.DriveInfo.GetDrives()
43.
availableDrives
44.
For
Each
drive
IO.DriveInfo
In
45.
d
= drive.RootDirectory.FullName
46.
d.Length = 3
47.
availableDrives.Add(d.ToLower)
48.
49.
Next
50.
51.
52.
Delegate
FileFoundEventHandler(
e
FileFoundEventArgs)
FileFoundEventArgs
_SearchQuery
_CurrentFoundFile
_AllFoundFiles
SearchQuery
FoundFile
AllFoundFiles
()
_AllFoundFiles.ToArray
))
._SearchQuery = SearchQuery
._CurrentFoundFile = FoundFile
._AllFoundFiles = AllFoundFiles
The FileFoundEventArgs class contains the following members:
StatusChangedEventHandler(
SearchStatusEventArgs)
SearchStatusEventArgs
_SearchStatus
Status
_FilesComparedSoFar
Integer
_DirectoriesSearchedSoFar
_UnsearchableDirectories
SearchStatus
FilesComparedSoFar
DirectoriesSearchedSoFar
UnsearchableDirectories
NewStatus
Status,
FilesSearched
._SearchStatus = NewStatus
._FilesComparedSoFar = FilesSearched
._DirectoriesSearchedSoFar = DirectoriesSearchedSoFar
._UnsearchableDirectories = UnsearchableDirectories
Enum
NotStarted
Initializing
GettingSubDirectories
GettingFiles
ComparingFileNames
Complete
Now you have read about the supporting classes that are needed in order to use the DriveSearcher class. Now we will do a quick overview of the DriveSearcher class and how it works
Imports
System.Threading
System.IO
DriveSearcher
QueuedDirectories
Results
SearchString
InvokingControl
FileFound
StatusChangedEventHandler
FileSearchCount
DirectoryCount
SetStatus(
Status)
Not
.SearchStatus
.InvokingControl.Invoke(SearchStatus, _
SearchStatusEventArgs(Status, FileSearchCount, DirectoryCount, UnsearchableDirectories))
SearchMain()
Do
SetStatus(Status.GettingSubDirectories)
nextDirectory
= QueuedDirectories(0)
Select
Case
True
ChildDirectories(nextDirectory).
GetType
=
Boolean
UnsearchableDirectories += 1
'increment the error counter
())
Directory
CType
(ChildDirectories(nextDirectory),
DirectoryCount += 1
QueuedDirectories.Add(Directory)
SetStatus(Status.ComparingFileNames)
TryResult
Object
= FilesInDirectory(nextDirectory)
TryResult.
'We already incremented for this access denied directory earlier
f
(TryResult,
FileSearchCount += 1
filename
= System.IO.Path.GetFileName(f)
filename.ToLower
Like
SearchString.ToLower
Results.Add(f)
InvokingControl.Invoke(FileFound,
FileFoundEventArgs(
.SearchString, f, Results))
QueuedDirectories.RemoveAt(0)
53.
Loop
Until
QueuedDirectories.Count = 0
54.
SetStatus(Status.Complete)
55.
56.
FilesInDirectory(
Folder
57.
SetStatus(Status.GettingFiles)
58.
Try
:
Directory.GetFiles(Folder,
"*.*"
, SearchOption.TopDirectoryOnly)
59.
Catch
False
60.
61.
62.
ChildDirectories(
63.
Directory.GetDirectories(Folder,
"*"
64.
65.
66.
67.
Shared
SearchDrive(
params
SearchParamaters)
68.
searcher
69.
With
70.
.SearchStatus = params.SearchStatusChangedEventhandler
71.
.InvokingControl = params.Invoker
72.
.FileFound = params.FileFoundEventHandler
73.
.QueuedDirectories.Clear()
74.
.QueuedDirectories.Add(params.DriveRootPath)
75.
.SearchString = params.FindFile
76.
77.
params.SearchStatusChangedEventhandler
78.
params.Invoker.Invoke(params.SearchStatusChangedEventhandler, _
79.
SearchStatusEventArgs(Status.Initializing, 0, 0, 0))
80.
81.
searchThread
Thread(
AddressOf
searcher.SearchMain)
82.
searchThread.Start()
83.
84.
85.
86.
87.
88.
89.
90.
availableDrives.Add(d)
91.
92.
93.
94.
95.
I hope you find this helpful, Please update this article if I left anything out! Please view my other Technet Wiki Articles