Click here to Skip to main content
Click here to Skip to main content

Multithreaded File/Folder Finder

By , 26 May 2010
 

Introduction

Why should you be interested in yet another search program?

  1. File Find is faster if you have more than one physical disk drive to search. Drives are searched in parallel and the search takes only as long as the slowest drive.
  2. File Find allows you to search for files, folders, or both.
  3. You may search using multiple masks in a single search.
  4. You may search for subsets of drives and / or folders using a combination of exclude and include filtering rules.
  5. Drives are selectable by drive letter or volume label; very handy for removable drives.
  6. You may run multiple copies of File Find at the same time.
  7. File Find does not need a constantly running background task to index files.
  8. Time range searches are to within one minute, and you may check by created, modified, or last accessed date.
  9. Two views of your data are offered: a listview of file and folder names, and a grid view with more detailed information. The grid view may be customized to show only the fields you are interested in. The listview may be saved to a text file while the grid view may be saved to a tab value separated file.
  10. Files and folders may be launched or deleted directly from the viewing form.
  11. File Find is user friendly in a multiple monitor system.
  12. You may customize drive searches by selecting which drive and paths are to be included or excluded during searches. These filter lists may be saved for easy reuse.
  13. File Find has an external interface so other programs may use File Find's rapid parallel search capabilities to locate files and/or folders of interest. File Find returns the names of the files and folders via named pipes.
Gridview

Listview

Installation and Usage

Download the FileFindBinaries.zip file, open it, and select either the .NET3.5 or 4.0 version directory. Copy the executables to a folder of your choosing. If you have .NET 4.0 installed, the 4.0 version is much faster. The FileFindBatchInterface program is optional, and is explained below in the External Interface topic.

You may want to create a desktop shortcut to launch FileFind.exe. For now, simply double click on the program to execute it.

By default, File Find will search all folders on all disk drives. Many of the system folders contain files that have no user files, so the first thing you might want to do is create a filter list to exclude those folders. Create a filter list by pressing the 'Filters' button, the 'New' button, and the 'Copy defaults' button. You should be looking at a form similar to the following:

Enter a name for your filter list and press the 'Save' button followed by the 'OK' button. Now, select the row containing the name of the filter list you just created and then press the 'OK' button. You will be back on the initial form and should see a 'Using filter list' message with the name of your filter list.

More detailed instructions for creating and editing filter lists may be found by selecting Help while on the 'Edit Filter List' form.

Key in a search mask. A mask consists of any characters that are valid in a file or folder name plus the wild card characters (* or ?). An asterisk will match zero or more characters and the question mark will match any single character. All matching is case insensitive. Multiple masks are separated by the semi-colon character (;). For example, *.jpg;xyz?.pdf will search for files with a file extension of .jpg and all PDF files with a four character name starting with xyz.

Begin the search by pressing the 'Enter' key while the focus is in the 'Search for' text area, or press the 'Start search' button. Feel free to explore the interface. You will not change any files on your system unless you press the 'Delete' button or key after selecting one or more rows on the grid view.

There is a simple way to see how much faster File Find is on your system. First, run a scan to get system caches loaded. Rerun the scan and note the elapsed time on the bottom of the form. Go to the Options->Sequential search selection on the menu and check it. Rerun the scan and compare the elapsed time to the prior search time. If you are searching multiple physical drives, File Find's search time in parallel mode is the elapsed time it takes to search the drive with the most files or the slowest response time.

You may run multiple copies of File Find at the same time, but you should not be running multiple copies and updating filter lists at the same time.

Filter lists may be shared among multiple copies, but each user has his own set of filter lists. Filter lists and various options are saved in isolated storage. Isolated storage is unique to the user and the assembly. If you decide to delete or move the program, you should remove the isolated storage by executing the program and selecting 'Options' → 'Remove saved options' from the main menu and then exiting the program.

If you are moving the executable program to another folder, you may want to export the filter lists before the move and import them after the File Find program has been moved. Export and import commands are available under the 'File' menu item on the 'Filter List Selection and Maintenance' form, which is shown when you press the 'Filters' button. Export and import are an easy way to transfer one or more filter lists between users.

If you have a prior version of FileFind and want to save the exclude list from it, you need to copy the new FileFind.exe into the same directory as the old FileFind.exe. The new FileFind.exe will automatically create a new filter list by copying the contents of the old exclude list. The name of the filter list will be 'Prior Excludes'.

Detailed usage instructions may be found under the Help menu. The help instructions are tailored to the various forms.

The Code

If you only want to use the find application, you may quit reading. The remainder of this article covers the application's architecture, some of the coding techniques used, and interesting problems encountered as well as their solutions.

The project was developed using Visual C# 2008 Express Edition, with a target framework of .NET 2.0. Version 3.0 of File Find forced me to move to .NET 3.5 for IsolatedStorageFileStream support. I have tested the code on XP, Vista, and Windows 7. If you have .NET 4.0 installed, I strongly recommend you recompile the program to use the 4.0 framework. It is noticeably faster.

Architecture

Logical / Physical Drive Resolution

Directory searches are IO intensive, which makes them perfect candidates for a multithreading architecture even on machines with a single core. The design of File Find takes advantage of this fact by starting a search thread per physical disk.

A physical disk may have more than one partition on it, so I had to match logical partitions to physical disks. This logic has been consolidated into the ResolveLogicalPhysicalDisks class. You pass in an ArrayList of drive letters, one letter per entry, in the form of:

  • C:\
  • D:\
  • F:\

and an ArrayList of resolved drives is returned:

  • C:\;F:\
  • D:\

The C and F partitions were found to be on the same physical drive. The two partitions will be assigned to the same search thread to avoid disk head contention. There may be other partitions on the drive as well, but the user did not select those partitions for searching.

The ResolveLogicalPhysicalDisks class offers synchronous and asynchronous method calls. The resolution process uses Windows Management Instrumentation (WMI) calls to perform the work. WMI is not particularly fast, but one advantage of the technique is any energy efficient drives in sleep mode will wake up and be ready for searching. Drive resolution is driven when the program starts or the disk selection is changed by direct selection or a new filter list. This could cause problems during program initialization as a resolution could be running when you select a new filter list. I use a ManualResetEvent in Form1.cs to prevent re-entry into the ResolveLogicalPhysicalDisks class. I also use the resolution process when drives or paths are being selected for building filter rules. Building filter rules does not have a re-entry problem.

If you use need to use the ResolveLogicalPhysicalDisks class in other programs, you may need to add a reference to System.Management manually.

Data Persistence and Data Communication Between Forms

All persistent data is accessible via the ConfigInfo class. ConfigInfo will load data from the prior File Find execution during program initialization and save all persistent data during termination. The debug constant as set in the project's properties is used to determine if the data is saved in isolated storage or an XML file. Debugging was simplified by being able to view and edit an actual XML file rather than data saved in isolated storage. Storing the data in XML format simplifies the addition of new features.

The ConfigInfo class also holds data needed in multiple forms. An example is form font information. A menu option allows the user to change the font being used. The font's characteristics are saved in the ConfigInfo class and are accessed by each form during the form's load process. Grid view information, the filter list collection, and menu options are also kept in the ConfigInfo class.

User Interface

The main thread, Form1.cs, displays the initial form and performs all user interface functions related to the search process. The list view and the grid view share the same area on the display form. You select which view you want by pressing the 'Grid view' or 'List view' button (text changes depending on which view is currently selected).

The most commonly used features are displayed on the start up form controlled by Form1.cs. This form contains the listBox1 and gridView controls which show, respectfully, the list and grid views. These two views show different information but occupy the same space on the form. The Form1 design form shows a grid view control that is smaller than the listBox1 control. The gridView control is on top of the listBox1 control. The bounds of the gridView control are set equal to the bounds of the listBox1 control when Form1 loads. The user may decide which control should be displayed at any time.

The buttons on the form are enabled and disabled as necessary. The text on the buttons will also change as necessary. For example, the 'Start search' button is disabled until a mask is entered. 'Start search' changes to 'Stop search' when a search starts. You may terminate the current search by pressing the 'Stop search' button, at which point you may briefly see a 'Stopping search' button. Pressing the 'Stopping search' button will stop the current search immediately.

It is fairly easy to overwhelm Form1 with messages from many scan threads. As the message arrival rate increases, the form's responsiveness drops. Consequently, I measure the number of messages per interval, and change how messages are displayed depending on how long the elevated rate persists.

The tracking variables and constants are:

private int msgsPerInterval = 0;
private const int MaxRate = 300; //maximum number of messages per MsgInterval
private const int PauseValue = 20; //milliseconds to pause busy threads
private const long MsgInterval = 500; //milliseconds between message intervals
private enum InUpdate { InUpdateNo, InUpdateSpeed, InUpdatePausing }
private InUpdate inUpdate = InUpdate.InUpdateNo;

No monitoring occurs until MaxRate messages have been processed. One of two actions occur if more than MaxRate messages are received during MsgInterval. First, the visible updating of the form stops via listBox1.BeginUpdate(); table.BeginLoadData(); commands, and the program enters InUpdateSpeed processing mode for a calculated period of time. At the end of the time period, the message arrival rate is checked again. If the rate is more than twice MaxRate, the scan tasks are asked to pause briefly (see SendFileInfo and SendDirectoryInfo below). All monitoring is turned off and the monitoring cycle starts again.

The remainder of the user interface consists of both forms and dialogs. All the forms and dialogs except Form1 have a FormLocation property which is set by the caller. The new form will attempt to display on the same monitor the calling form is located on. This is especially useful if multiple File Finds are executing.

Sample code to accomplish this in the calling form is:

using (AboutBox aboutDialog = new AboutBox())
{
    aboutDialog.FormLocation = this.Location;
    aboutDialog.ShowDialog();
}

The property in the new form is defined as:

private Point location = new Point();
private bool locationSet = false;

public Point FormLocation
{
    get { return location; }
    set
    {
        location = value;
        location.X += 10; //add a small offset value
        location.Y += 10;
        locationSet = true;
    }
}

Threads

There are two types of threads: the user interface thread and the scanning thread.

File Find has only one user interface (UI) thread but may have many scan threads. The UI thread owns the start up form and handles the most common user interface functions. The UI thread also controls the scanning threads.

File Find creates one thread for each physical disk being searched as identified by the ResolveLogicalPhysicalDisks class. The threads are tracked in a List<Thread> class named searchThreads. A scan thread is added to searchThreads when the thread is created, and removed when it ends. The search is complete when searchThreads.Count is zero. The thread's name is based on the names of the drives the thread is to search.

The StartSearching() method in the UI is called when the user presses the 'Start search' button. StartSearching() validates all requirements have been met (drive resolution must be complete, at least one drive selected, and one or more file masks provided) before building and starting the DiskScan threads.

An instances of the DiskScan class is created for each resolved drive to be searched. The argument list for the class constructor contains some information fields and a set of delegates to facilitate passing information between the UI and the scanning thread. The constructor in DiskScan is defined as:

public DiskScan(
    ContainerControl form, //the user interface
    Delegate DsplyMsg, //send text messages
    Delegate SendDir, //send directory information
    Delegate SendFile, //send file information
    ManualResetEvent terminateRequest, //receive a termination request
    Delegate ThreadStopping, //send an end of thread message
    DateTimeInfo selectedDateTime //provides date/time range information
)

The matching field definitions in the UI are:

private delegate void DelegateSendMsg(String s);
private DelegateSendMsg m_DelegateSendMsg;
private delegate void DelegateThreadStopped(string s);
private DelegateThreadStopped m_DelegateThreadStopped;
private delegate int SendFileInfo(FileInfo fi, string volumeId);
private SendFileInfo m_SendFileInfo;
private delegate int SendDirectoryInfo(DirectoryInfo dir, string volumeId);
private SendDirectoryInfo m_SendDirectoryInfo;

The SendFileInfo and SendDirectoryInfo delegates serve a dual purpose. DiskScan uses the delegates to send information to the UI for display, and the UI returns the number of milliseconds the DiskScan thread should pause before sending more information. The pause interval is non-zero only if the UI is experiencing an excessively high message rate.

The constructor's argument list was becoming unwieldy, so some information is given to the DiskScan thread by using class properties before adding the thread to the searchThreads list and starting the thread. The following code in the UI creates, tracks, and starts the thread.

foreach (String resolvedDrive in resolvedDrives)
{
    // create worker thread instance
    DiskScan diskScan = new DiskScan(this,
        m_DelegateSendMsg, m_SendDirectoryInfo, m_SendFileInfo, 
        pleaseTerminate, m_DelegateThreadStopped, dateTimeInfo);

    diskScan.SearchingDrives = resolvedDrive;
    if (filesOnlyRadioButton.Checked)
        diskScan.SearchForFiles = true;
    else if (foldersOnlyRadioButton.Checked)
        diskScan.SearchForFolders = true;
    else if (filesAndFoldersRadioButton.Checked)
        diskScan.SearchForBoth = true;
    diskScan.IFindFiles = fileMasks;
    Thread searchThread = new Thread(new ThreadStart(diskScan.Run));
    searchThread.Name = resolvedDrive;
    searchThreads.Add(searchThread);
    searchThread.Start();
} //ends foreach(String resolvedDrive in...

Thread termination depends on unique thread names, so I used the names of the drives being searched by the thread as the thread name. The UI will search the searchThreads list for the thread name and remove it. The search is finished when searchThreads is empty. The diskScan.Run() method is wrapped in a try block to ensure the following command is always issued just before the scan thread terminates:

try
{
    m_form.Invoke(ThreadTerminating, 
                  new Object[] { Thread.CurrentThread.Name });
}
catch {}

Thread termination runs asynchronously in the UI so all references to and operations against searchThreads must be protected by a lock on threadobj.

There are many reasons to terminate a search early – you mistyped the mask, you noticed you were using the wrong filter list, you already see the file you are searching for, etc. The UI allows the user to terminate a search early via the 'Stop searching' button. When the 'Stop searching' button is pressed, the ManualResetEvent pleaseTerminate is set. DiskScan threads are given a reference to the pleaseTerminate event and DiskScan will periodically check to see if the event has been signaled. If it has, DiskScan will terminate. The pleaseTerminate event will also be set if the form is closing or the external interface closes the named pipe.

Multiple Monitor Support

I normally work with two monitors. Windows default form placement actions work well when on the primary monitor, but do not work well at all when the File Find form is on the secondary monitor; additional forms show up back on the primary monitor. Consequently, I added a FormLocation property to the pop up forms so I could position the pop ups close to the current form's location.

The caller's code is as simple as:

using (SelectFilterListToCopy copyFilterList = new SelectFilterListToCopy())
{
    copyFilterList.FormLocation = this.Location;
    copyFilterList.ShowDialog();
    . . .

The pop up form's property definition is:

private Point formLocation = new Point(0, 0);
private bool formLocationSet = false;
public Point FormLocation
{
    get { return formLocation; }
    set { formLocation = value; formLocationSet = true; }
}

External Interface

File Find has the ability to rapidly search multiple disk drives. Other programs may need to search multiple disk drives as well. I could have created a class other programs would use, but the asynchronous nature of the search and presentation of search results would make for a very complex class. I decided to create a command line style interface to provide search criteria and to use a named pipe to return search results. Arguments are:

  • FilterList: FilterList provides the name of the filter list to use. The filter list must already exist. Create the filter list by executing FileFind.exe and point to the directory containing the FileFind.exe when you launch FileFind.
  • PipeName: PipeName provides the name of the pipe to use. A pipe created on another system may be used, but FileFind currently has no sign on protocols. I tested cross system by signing on as the same user on two different machines.
  • Masks: Masks are the same as the 'Search for' field on File Find's main form.
  • FilesFolders: This determines if you are searching for files only, folders only, or both. Valid values for FilesFolders may be:
    • Files
    • Folders
    • Both
  • Visible: allows you to display the FileFind form (normally not visible), helpful for debugging your application. Valid values are:
    • Yes
    • No

The -keyword is not case sensitive, but blanks or spaces are not allowed between the semi-colon and the value. Place double quotes around the entire argument if you need to put spaces into the value.

  • Masks: *.jpeg not valid, space follows semi
  • Masks:*.jpeg valid
  • FilterList: My defaults not valid, space embedded in argument value
  • "-FilterList:My defaults" valid

A C# sample program, FileFindBatchInterface, implementing the above interface call is provided. The sample allows you to run synchronous or asynchronous named pipes. Define and save any filter lists you want to use that need to be defined by executing File Find before running FileFindBatchInterface.exe. No path is needed if you place both FileFind.exe and FileFindBatchInterface.exe in the same directory.

The threading structure for the sample program is very similar to the File Find structure: a List<Thread> to track running tasks and a ManualResetEvent to request thread termination. However, the PipeServer thread cannot poll for the termination signal while it is waiting for a pipe connection. The following code works fine for asynchronous pipes:

WaitHandle[] waitHandles = new WaitHandle[] 
{
    new AutoResetEvent(false), //requested termination
    new AutoResetEvent(false) //pipe I/O completion
};

waitHandles[0] = pleaseTerminate;
using (NamedPipeServerStream serverPipe = new
NamedPipeServerStream(pipeName, PipeDirection.In, 1,

PipeTransmissionMode.Message, PipeOptions.Asynchronous))
{
    // wait for a client...
    UpdateStatus("Waiting for asynchronous connection");

    IAsyncResult waitConnection;
    try
    {
        waitConnection = serverPipe.BeginWaitForConnection(null, null);
    }
    catch (Exception ex)
    {
        SendMsg("Server BeginWaitForConnection failed\n" + ex.Message);
        return;
    }
    waitHandles[1] = waitConnection.AsyncWaitHandle;
    WaitHandle.WaitAny(waitHandles);
    if (pleaseTerminate.WaitOne(0, true))
        return;
    //. . . processing continues

WaitHandle.WaitAny(waitHandles) will block until the pleaseTerminate event occurs or the pipe connects. The pipe server checks to see which event occurred and takes the appropriate action.

Things are a bit more difficult for a synchronous pipe as no connection event is available. The pipe server is blocked at a WaitForConnection call and will not see the pleaseTerminate event until a pipe connection occurs. Consequently, the UI thread must provide a connection to the pipe by opening and closing the pipe.

using (NamedPipeClientStream pipe = 
  new NamedPipeClientStream(".", pipeName, PipeDirection.Out, PipeOptions.None))
{
    pipe.Connect(3000);

Futures

I want to improve searching of networked disks and look into virtual mode for ListView controls.

I have tested this code on Windows XP, Vista, and Windows 7. The code has been in use for well over two years and seems to be stable.

Acknowledgements

  • I wish to thank reinux for his article "Converting Wildcards to Regexes", published at http://www.codeproject.com/KB/recipes/wildcardtoregex.aspx. His routine allowed me to rapidly convert wild card characters to Regular Expressions so I could easily match masks to names.
  • I used a modified version of Simon Morier's code to associate logical partitions with physical disks. I found Simon's article at http://www.codeproject.com/KB/system/usbeject.aspx.
  • I also want to thank Dave Midgley for his excellent article on reparse points at http://www.codeproject.com/KB/vista/ReparsePointID.aspx.
  • I created a modified version of Carl Daniel's “File system enumerator using lazy matching” code found at: FileSystemEnumerator.aspx.
  • I did not create the flash light icon. It came from a free icon site somewhere on the web. I thank who ever created it and made it publicly available.
  • I also want to thank the folks who sponsor CodeProject.com as well as the many contributors. I obviously use this site a lot!

History

  • Version 2.1.0.17 - new base line.
  • Version 3.0.0.0 - added include/exclude filter lists.
  • Added external interface.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Roger500
Software Developer (Senior) retired
United States United States
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Generalfeature request: folder inclusions instead of exclusionsmemberDerek Read5 Oct '09 - 11:57 
I'm quite impressed with this (simply by running the executable) as it seems to be a very good demo for multi-threading which I have been looking for. I have only VS 2005 and so need to get 2008 installed to have a look at your code (and see if I can extend it for my own needs).
 
One big feature this tool is missing that would make it great for people to use in all instances would be to allow the search path to be restricted below the drive's root. You do have an option to exclude certain paths, however, you don't have the opposite option which is to skip all folders except folders specified for a given drive.
 
For example, if I only wish to search within the following paths:
 
C:\SomeFolder\SomeSubFolder
D:\
 
Using the current "Exclude" feature, every folder except the one listed above would need to be listed in the exclusions for drive C. A list of all folders could be found using COMMAND DIR with those folders I do wish to search being removed from that list but that is not exactly user friendly and adding them all through your UI would take a long time for any significant number of folders.
 
The alternative is to let the application chug away on my drives and then parse the resulting list afterwards, and although this tool uses practically no CPU cycles it does take a long time to complete that process, and then the results need to be parsed later on (your sorted view allows this to be done quite easily so that is good).
 
----------------
Derek Read

GeneralRe: feature request: folder inclusions instead of exclusionsmemberRoger5005 Oct '09 - 17:38 
You are the second person making this request and I intend to implement it. I envision allowing the user to have multiple include or exclude lists and allow for list selection before a search. The use could dynamically create the list or select from previously saved lists.
 
Should I allow for selection of multiple lists? If so, how would collisions between include and exclude lists be handled?
GeneralRe: feature request: folder inclusions instead of exclusionsmemberDerek Read6 Oct '09 - 15:02 
I haven't thought this through completely, but my gut tells me you might consider redesigning the way drives are specified and include additional options there on a per-drive basis, essentially combining three features into one dialog.
 
- List all found drives. Let the user select a checkbox for each drive to be included in searches.
- A second checkbox for each drive would specify whether paths you specify for that drive are inclusive or ignored.
- A textbox for each drive would contain the paths to include or exclude (depending on the previous checkbox) for that drive.
 
When include is specified only folders specified are searched and no others.
When ignore is specified all folders are searched except those specified.
 
The alternative would be to have no checkbox and two textboxes for each drive. Perhaps a more developer-oriented way of thinking? In this case all folders listed in the "include" textbox could be searched and any "ignore" paths specifies would be skipped. If an ignore path is specified and it is not a subfolder of an "include" folder then it would be a meaningless entry.
 
I think (<- emphasis needed there) both of these methods would allow you to search specific folders only. The part I have not thought through yet is whether or not one makes things (easier to specify than the other.
 
----------------
Derek Read

GeneralRe: feature request: folder inclusions instead of exclusionsmemberRoger5006 Oct '09 - 17:19 
Thanks for your input. Plenty to think about. I also need to keep the process simple. Drive and folder specification needs to be quick or it defeats the whole purpose of a fast find application.
GeneralRe: feature request: folder inclusions instead of exclusionsmemberRoger5002 Jun '10 - 17:34 
Drive and folder include and exclude logic is now available and, I hope, simple to use. Suprisingly, the include/exclude logic is actually faster than the old exclude only logic. I think a large part of the performance increase was due to using strongly typed lists instead of ArrayList.
GeneralNicememberJamesMMM21 Sep '09 - 6:14 
but a couple suggestions:
 
1. allow a parameter to be passed to it so it can search a directory via the right click context menu so you can simply search a directory you've clicked on
 
2. Implement a status bar that shows the current drive/directory it is searching.
GeneralRe: NicememberRoger50021 Sep '09 - 6:49 
To answer #2 first, you have a status line on the bottom of the form showing which drives are being searched.
 
For #1, are you looking to drive FileFind from another application?
GeneralRe: NicememberJamesMMM21 Sep '09 - 7:56 
nevermind about item 1. I think it would be difficult to implement since
the app is multi-threaded.
 
Item2: i would like to be able to right click on a drive letter or foldername and have the filefind application open and search only that
drive/folder rather have having to always exclude/include drives via the menu. The app can default to include all drives when started the normal way via "run". I know i would need to add the context item to the registry via SendTo item to enable this.
GeneralRe: NicememberRoger50021 Sep '09 - 9:47 
You already have a status line on the bottom of the form showing which drives are being searched unless you are running a very old version of FileFind.
 
I will have to look into how to drive an application with parameters via a context right click. However, I like the idea.
GeneralMy vote of 2mvpDave Kreskowiak16 Sep '09 - 9:10 
It's a decent start, but you've left out the description of the code, how the threading model is handled, and the concepts behind it all.
QuestionWhy bother?memberRusty Shakelford3 Sep '09 - 18:58 
Did you fall asleep writing this article? The links to code and demo are broken. Poor. Poor. Poor. D'Oh! | :doh:
AnswerRe: Why bother?memberRoger5004 Sep '09 - 4:28 
Interesting! It is fairly obvious the code, the sample and the article is currently trashed. All features worked when originally published as proven by other comments. I will update the article with descriptions of enhancements repost with current source and sample later today. Thanks for the heads up.
GeneralMy vote of 1memberAxelM19 Aug '09 - 22:29 
-
GeneralNetwork drivesmemberrctaubert25 Jun '09 - 11:21 
Is there a way to scan network drives???
 
I tried mapping a drive but it still didn't show up.
 
Also, it would be nice to have an abort button.
GeneralRe: Network drivesmemberRoger50025 Jun '09 - 12:17 
I map a network drive to a letter and then start FileFind. The "Resolved logical/physical disks" status bar on the bottom of the initial should show the mapped drive letter. The letter should also be displayed in the "Disk selection" list when you press the "All disks" button on the initial screen. Insure the mapped drive is selected; it should be by default. You might also insure the drive letter you used is not excluded by examining the "Excludes" list.
 
I have been looking at how to find and search network drives without requiring a mount. I first became interested in that issue when I installed Windows 7 RC with the new VM option. No joy so far.
 
There are two ways to stop a search. The "Start search" button changes to a "Stop search" button when the search begins and flips back to the "Start search" status when the search ends or you may terminate the application by pressing the X button in the upper right corner of the form. I have had problems cancelling the search when a very high number of files are being found. The program just not not receive enough CPU time between interrupts to process the cancel. A simple fix is to halt automatic scrolling via the Options->Auto scrolling selection.
GeneralRe: Network drivesmemberrctaubert25 Jun '09 - 14:34 
Sorry I missed seeing that the Start button toggled. Old age.
 
Interesting! I had downloaded your code and demo for 18 Jun 2009. I first ran the program using the source code and it definitely DOES NOT show anythng but the c drive.
 
After receiving you reply I went back and tried your demo. That works as advertized.
 
I ran a test between a recursive file search program I found on the internet and updated to VB.net. I am running the test on a Toshiba laptop with a dual core T2600 2.16GHz processor, 4 GB of RAM and running 32-bit Vista Ultimate over a 1GB wired network. I mapped a drive to the Shared Folder 'Music' located on my Windows Home Server. This folder contains 16724 music files (.wma) and album cover graphic. I used the mapped drive and mask (*.wma).
 
With your program I turned off the Automatic Scrolling and tried both with and without Scan via enumerator. The results are as follow:
 
Your program:
Without 'Scan via enumerator': 2 min 48 sec
With 'Scan via enumerator': 2 min 46 sec hardly a significant difference.
 

With my program I collect all of the file titles in an array and then return the entire array. My program uses the FILESYSTEMINFO class
 
My program: 26.536 sec
 

 
I also ran a search of my entire hard drive (C:\) with the same criteria. The drive contains 222,056 files in 40,545 folders.
 
Your program: 2 min 9.250 sec Much better but a long way from your results.
My program: 50.045 sec.
 
The numbers you show for your test are much more impressive than what I got. I don't for a minute think you fudged your results. But, I am very curious about what differences there could be in our setups that could cause such a drastic spread. You really didn't describe your setup. Are your computers significantly faster than what I am using??? Are the files on CodeProject your latest creations???
GeneralRe: Network drivesmemberRoger50027 Jun '09 - 12:08 
When I was performing my timing tests, I always ran the the tests at least twice. The first test will almost always have to access directory information from the disk while the second test almost always has the disk information cached by the OS. Consequently, the second test is always much faster.
 
I have three systems, a quad-core CPU running at 2.2 Gh with 8GB of memory and two dual core laptops. One of the laptops is a Vista 64 system and the other is Vista 32. All are connected via a wired 1GB network. I also have a access to an XP system on a 100 MB ethernet.
 
Locally and over the 1GB ethernet, scanning with or without the enumerator makes little difference but I saw significant differences on the 100MB ethernet which is when I switched from FileSystemInfo to the enumerator for networked disks.
 
I will download my posted source code and check for a C: drive only display.
I will also rerun my timing tests and post the results back to you. Thanks for your feed back.
GeneralRe: Network drivesmemberrctaubert29 Jun '09 - 1:24 
At least one of your machines is a lot faster than mine.
 
I always run tests multiple times, if for no other reason than to account for other network traffic that could slow things down.
 
As soon as Code Project puts the new downloads up I will check them out. Next time you are looking at the code could you add 'stopwatch' to display the time elapsed for the search? It is always interesting to know how long it takes.
 
I'll also re-run the tests on my laptop and my desktop.
 
If you want to take this off-line my address is rctaubert at eaglecom dot net.
GeneralRe: Network drivesmemberRoger50029 Jun '09 - 6:52 
What level of FileFind are you running? The 2.0.15 version has a stop watch display on the status bar at the bottom of the form.
 
Your find may be faster than mine due to several unrelated reasons:
1. I build two displays; a file/folder name list and a grid view for each successful find (a hit).
2. I have found automatic scrolling is more expensive as the hit ratio increases but you turned off auto scrolling which is good when experiencing a high number of hits. I find auto scroll to be useful when I am looking for a specfic file and want to stop the search when the file is found.
3. I have both esata II and USB drives.
 
The following tests were run with a different program that fetchs the names of all files on the assigned disk. The GATEWAY machine owns the disk and the other two machines access the disk remotely via a 1GB ethernet link.
 
Machine name: GATEWAYPC, 64 bit mode
Microsoft Windows NT 6.0.6001 Service Pack 1 - Vista
CLR Version: 2.0.50727.3074
AMD64 Family 16 Model 2 Stepping 3, AuthenticAMD
System has 4 processors and 10 logical disks
Searching P:\Tera01 (Fixed) via FileInfoSystem
Processed 23,706 files and 4,640 directories
Search completed, search time: 00:00:02.7253769
Searching P:\Tera01 (Fixed) via Enumerator
Processed 23,706 files and 4,640 directories
Search completed, search time: 00:00:01.9477458
 
Machine name: TRAVELER, 64 bit mode
Microsoft Windows NT 6.0.6002 Service Pack 2 - Vista
CLR Version: 2.0.50727.4016
Intel64 Family 6 Model 23 Stepping 10, GenuineIntel
System has 2 processors and 5 logical disks
Searching Z:\Tera01 (Network) via FileInfoSystem
Processed 23,366 files and 4,494 directories
Search completed, search time: 00:01:56.7731196
Searching Z:\Tera01 (Network) via Enumerator
Processed 23,366 files and 4,494 directories
Search completed, search time: 00:01:46.4785183
 
Machine name: WIN7B2TOSHIBA, 32 bit mode
Microsoft Windows NT 6.1.7100.0 - Windows 7
CLR Version: 2.0.50727.4918
x86 Family 6 Model 14 Stepping 8, GenuineIntel
System has 2 processors and 3 logical disks
Searching z:\Tera01 (Network) via FileInfoSystem
Processed 23,366 files and 4,494 directories
Search completed, search time: 00:04:16.4307197
Searching z:\Tera01 (Network) via Enumerator
Processed 23,366 files and 4,494 directories
Search completed, search time: 00:04:16.2052122
 
My first timing on the Windows 7 machine was a remarkable 23 minutes! I traced the problem to the Bullguard security package. I uninstalled Bullguard and installed Avast. That lead to the above timings. I'll have to play around some more especially as I have Windows 7 on my Gateway machine as well as Vista.
 
I also noticed the difference in the number of files when the drive was scanned locally versus remote. I will have to determine exactly which files although I suspect they will be system files. I know I have a paging file on the disk.
 
My time is limited this week as I am moving next week. However, I do want to persue this issue. A friend of mine is using the program at work and he has a LOT of network disks to search.
GeneralRe: Network drivesmemberrctaubert29 Jun '09 - 8:41 
I don't envy you your move.
 
Both the source code and the demo say they are v2.1.0.15. However, as I stated previously, the source code will not show anything but C:\. The demo shows the C: drive as well as all mapped drives. Did you say that you HAD upload fresh copyies to Code Project or that you were going to????
 
The following is from your About window:
File Find searches for file and/or folder names matching one or more masks.
User: rctaubert (User)
Machine name: ROBERTSLAPTOP, 32 bit mode
Microsoft Windows NT 6.0.6002 Service Pack 2
CLR Version: 2.0.50727.4016
x86 Family 6 Model 14 Stepping 8, GenuineIntel
System has 2 processors and 4 logical disks
Physical memory: 3,210,145,792 bytes
 
Your machines are definitely faster than mine. Your explanation about the two displays you build simutaneously and the difference in our systems could certainly account for some of the long times but not all. I'll have to try to determine if I have something similar to your Bullguard problem. I use AVG and have been happy with it.
 
I can't believe my laptop is that slow. It just isn't that old. Oh well. Guess I will have to start looking for an upgrade.
 
I still need to try this on one of our desktops. I'll let you know what I find.
 
Don't wear yourself out moving.
GeneralRe: Network drivesmemberRoger50029 Jun '09 - 10:38 
The v2.0.15 is the most current released code. I downloaded the source, compiled the program and saw all of my drives. My version 2.0.16 has only minor changes, not worth uploading unless I find a definite problem.
 
I tried changing the Invoke calls from DiskScan threads to the Form1 thread from sync to async calls. The change slowed things down on the local machine but sped things up on remote drives. Ah, more research Wink | ;-)
 
Time permitting, I may ship you another program I wrote that displays the physical characteristics of the drives on a system. That may shed some light on the missing drives problem.
 
Back to the boxes Big Grin | :-D
GeneralClass Librarymemberrctaubert8 Apr '09 - 5:43 
Great program.
 
I think your code would be even more valuable if you separated all the "File/Folder Finder" code into a Class.
 
I was going to try doing this myself but I am a VB.net programmer. Not all of your C# code will convert to VB. VB does not yet support iterators.
 
As a class it could be used with any of the .net languages.
 
I have a Recursive Search class that I built by modifing some code I found on Code Project, that I have been using, but it is slow.
 
Basically, I give it a starting drive or directory, a mask to search for and it returns an array I populate a ListView Control.
 
You could incorporate all of your options on the form as properties.
 
Just a thought.
 
Thanks for sharing.
GeneralRe: Class LibrarymemberRoger5008 Apr '09 - 7:51 
Ouch! You don't want much do you? Smile | :)
 
I actually thought about writing the program around a finder class but decided it would be far too complicated for a first try. Now that I understand some of the issues better, I may give it a second look. Some of the "real time" outputs will be especially interesting to fit into a simple interface.
 
I have already added a status bar and improved the error checking concerned with security permissions (an area I am not very familiar with). I would love to have a menu list appear when you hover over a line or cell. The menu would offer you various allowable file options (rename, delete, copy, move, launch).
 
Thanks for your comments.
GeneralRe: Class Librarymemberrctaubert8 Apr '09 - 8:16 
Sorry about that (lol). I guess the question was more of 'would it be possible to separate the file/folder search part of your code into a class' and still maintain the integrity of you original goal.
 
I will definitely use your program as if to do searches of my hard drive. Nine times out of ten I am only looking for a particular file with a particular name. Windows search wants to return files with the right name, files which contain the name, folders, zip files. I get tired of having to search through hundreds of returned filenames that have nothing to do with my request. Your app fits that bill.
 
But I do have several vb.net apps I have written which search the drive, using the recursive file class that I have, for a particular type file type (mostly .wma) and then perform specific tasks on them. As I said my class is slow but serviceable. Just thought that if it would work as well for you your code might produce a faster search.
 
So whereas you want a program to search your drive and possibly perform a task on the returned files based on the options you select, I am looking for a class that will search for a drive quickly and return ONLY a list of the files. The only options I would need would be the ability to specify the starting location, search mask (e.g. *.wma, *.mp3), and whether to do a recursive search or a single directory.
 
My apps use my recursive search class to find all' the files that match the criteria and then return them in an array. Once the main app has the array whatever task I have in mind are performed against the names in the array.
 
That may not fit your goals and I am not asking you to venture outside of those goal.
GeneralRe: Class LibrarymemberRoger5008 Apr '09 - 15:57 
It would not be difficult to convert the DiskScan thread logic to a class. Some of the properties would be begin/end time, search masks, starting location, hidden file search option, file/folder/both option and, as you requested, a recursion option. Additionally, several methods for returning data would be required. The class could build an array of results or return the results via a delegate as matches are found.
 
The DiskScan routine already handles multiple disk drives but the class approach would not be taking advantage of multithreading. However, it may give you a faster search than the one you have especially if you are searching network mapped drives.
 
Regards,
Roger

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 26 May 2010
Article Copyright 2009 by Roger500
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid