Introduction
WinSearchFile is a program that I developed and I usually use it to search files on my PC.
Sometimes the search engine integrated with Explorer doesn't work fine, especially when I try to find text contained into files, so I decided to build my own search program.
There are a lot of search programs available to install on your PC but this one, without indexing your data, is simple and fast enough to help you in your search.
Inside the application
WinSearchFile layout is simple and quite similar to the Explorer integrated search. It is possible to write a pattern search (wildcards admitted) and/or a text to search into file contents (you can also decide for a case sensitive search).
In the "look in" area, you have all the disks of your computer (network connection included). To obtain this list, I use the DiskCollection
class developed by dmihailescu in his Get Logical Drives Information article.
private void LoadDisksComboBox()
{
disksListBox.Items.Clear();
DiskCollection diskColl = new DiskCollection();
if ( diskColl.Load() )
{
foreach(DiskCollection.LogicalDriveInfo diskinfo in diskColl)
{
disksListBox.Items.Add(diskinfo.Name.ToString() +
": "+ diskinfo.Description );
}
}
else
{
for (char Ch = 'A'; Ch <= 'Z'; Ch++)
{
string Dir = Ch + @":\";
if (Directory.Exists(Dir))
{
disksListBox.Items.Add( Ch+ @":" );
}
}
}
}
Application shows alerts when you check a not-ready disk.
In the WinSearchFile application, I use threads to make the same search simultaneously on different targets; I use a thread for each target drive.
private void btnSearch_Click(object sender, System.EventArgs e)
{
for (int i = thrdList.ItemCount()-1; i>=0; i--)
{
thrdList.RemoveItem(i);
}
listFileFounded.Items.Clear();
ContainingFolder = "";
SearchPattern = txtSearchPattern.Text.Trim();
if (SearchPattern.Length == 0)
{
SearchPattern = "*.*";
}
SearchForText = txtSearchText.Text.Trim();
Dirs.Clear();
foreach (int Index in disksListBox.CheckedIndices)
{
String Dir = disksListBox.Items[Index].ToString().Substring(0,2);
Dir += @"\";
if (CheckExists(Dir))
{
Dirs.Add(Dir);
}
}
foreach (String Dir in Dirs)
{
Thread oT;
string thrdName = "Thread" + ((int)(thrdList.ItemCount()+1)).ToString();
FileSearch fs = new FileSearch(Dir, SearchPattern,
SearchForText, CaseSensitive, this, thrdName);
oT = new Thread(new ThreadStart(fs.SearchDir));
oT.Name = thrdName;
SearchThread st = new SearchThread();
st.searchdir = Dir;
st.name = oT.Name;
st.thrd = oT;
st.state = SearchThreadState.ready;
thrdList.AddItem(st);
oT.Start();
}
}
Data about searching threads is stored in a list, and during the search process, you can see how many threads are running/ready/cancelled.
Threads use the FileSearch
class to do their work. To update controls or data structures on main threads, use delegate functions. I defined a delegate function for the AddListBoxItem
method:
public delegate void AddListBoxItemDelegate(String Text);
public void AddListBoxItem(String Text)
{
Monitor.Enter(listFileFounded);
listFileFounded.Items.Add(Text);
Monitor.Exit(listFileFounded);
}
and one to update the thread state:
public delegate void UpdateThreadStatusDelegate(String thrdName,
SearchThreadState sts);
public void UpdateThreadStatus(String thrdName, SearchThreadState sts)
{
SearchThread st = thrdList.Item(thrdName);
st.state = sts;
}
On clicking the "Stop search" button, all the running threads are cancelled using the Abort
method.
private void btnStop_Click(object sender, System.EventArgs e)
{
if (InProgress)
{
for (int i= 0; i < thrdList.ItemCount(); i++)
{
if (((SearchThread)thrdList.Item(i)).state ==
SearchThreadState.running)
{
((SearchThread)thrdList.Item(i)).state =
SearchThreadState.cancelled;
Thread tt;
try
{
tt = ((SearchThread)thrdList.Item(i)).thrd;
tt.Abort();
}
catch
{
}
}
}
}
}
On double clicking on a result listbox item, WinSearchFile will open the corresponding containing folder.
To quick launch WinSearchFile, you can create a shortcut to it on your desktop and assign to this one a shortcut key.
Conclusion
I hope you enjoy this article.
New WinSearchFile version
The new WinSearchFile 2.0, built using Visual Studio 2005 and C# 2.0, contains the following new features:
- Single Instance Application using code written by Eric Bergman-Terrell.
- Search inside PDF files.
- Regular expression searching.
- Searching using IFilter.
- Max directory visit depth.
- File
Creation Time
or Last ACcess Time
or Last Write Time
searching
- directory list to search into.
Save results
button.
Here is a new screenshot:
About IFilter
User can decide to use installed IFilter to extract plaintext from files. To implement this interface I used 2 class developed by Dan Letecky.
The following code shows where I try to use IFilter to get plaintext:
public static bool FileContainsText(String FileName,
String SearchForText, bool CaseSensitive,
bool UseRegularExpression, bool UseIFilter)
{
bool Result = (SearchForText.Length == 0);
if (!Result)
{
if (Parser.IsParseable(FileName) && UseIFilter)
{
string content = Parser.Parse(FileName);
if (content.Length > 0)
{
Result = containsPattern(SearchForText,
CaseSensitive, UseRegularExpression, content);
return Result;
}
}
if (FileName.ToLower().EndsWith(".pdf"))
{
Result = SearchInPdf(FileName, SearchForText,
CaseSensitive, UseRegularExpression);
}
else
{
bool Error;
String TextContent = GetFileContent(FileName, out Error);
if (!Error)
{
Result = containsPattern(SearchForText,
CaseSensitive, UseRegularExpression, TextContent);
}
}
}
return Result;
}
The following screenshot shows the about box where it's possible to get the list of installed IFilter. To get this list I used a class developed by vbAccelerator.com.