using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Pipes;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Microsoft.VisualBasic.FileIO;
/// <summary>
/// File Find searches for file and/or folder names matching one or more masks.
/// A mask may contain wild card characters (* or ?). An asterick will match one or more characters and the question
/// mark will match any single character. All matching is case insensitive.
/// </summary>
///
//To do:
//
//Added Invisible form if arguments present
//Added Export/import FilterListCollection
//Added a "take a breath" logic to DiskScan
//Accepts argument for locations and masks to search
//Allowed include / exclude location lists
//Add a "take a breath" logic to DiskScan
//Added Volume name to grid
//Added columns to view to grid
//Problem: last row remained visible when all rows were selected for delete
//Fixed: Form1 error when exiting under Windows 7
//Created folder & file column save/restore
namespace FileFind
{
public partial class Form1 : Form
{
//--------------------------------------------------------------------------------------------------
//grid view table, constants and variables
//table columns, update BuildGridColumnSelectionMenu when adding to or deleting from these constants
private const string GTFILENAME = "File name";
private const string GTSIZE = "Size";
private const string GTDISK = "Disk";
private const string GTVOLUMEID = "Volume Id";
private const string GTDIRECTORY = "Directory";
private const string GTCREATED = "Created";
private const string GTMODIFIED = "Modified";
private const string GTLASTACCESSED = "Last accessed";
//holds local copy of grid view column ordering & visibility information
private DataTable table; //constructed in BuildGridTable()
GridInfoCollection
foldersView = null, //folders only display
filesView = null, //files or files and folders display
usingView = null; //which view (files or folders) is currently active in the grid
//used to remember which cell was clicked in a prior grid event
private int cellRowClicked = -1;
private string cellColumnName = null;
//--------------------------------------------------------------------------------------------------
//various button titles and message texts
private const string STARTSEARCH = "Start search";
private const string SEARCHSTOPPING = "Search stopping";
private const string STOPSEARCH = "Stop search";
private const string ITEMSFOUND = "Items found: ";
private const string MENUGRIDVIEW = "Grid view";
private const string MENULISTVIEW = "List view";
private const string SEARCHALLDISKS = "All disks";
private const string SEARCHSELECTEDDISKS = "Selected disks";
private const string SEARCHNONE = "None";
private const string DELETE = "Delete"; //used with sortOutputButton
private const string SORTOUTPUT = "Sort output"; //used with sortOutputButton
private const string SELECTTIMERANGE = "Select time range";
private const string SELECTEDTIMERANGE = "Selected times";
private const string SCANNINGVIAENUMERATOR = "Scanning via enumerator";
//--------------------------------------------------------------------------------------------------
private DateTimeInfo dateTimeInfo; //holds return info from SelectDateTimeRange
//--------------------------------------------------------------------------------------------------
// Variables dealing with disk drive resolution
// Logical to physical drive resolution is drived asynchronously by FetchAllDisks
// or FetchSelectedDisks. The async delegate was used to eliminate
// a brief pause caused by the WMI calls just before DiskScan threads were
// attached. ResolveLogicalPhysicalDisks.BeginResolveDrives allows the WMI calls
// to run as soon as selectedDisks is loaded. The thread attach logic
// waits for ResolveLogicalPhysicalDisks.EndResolveDrives to insure disk partitions have
// been resolved before the threads are attached. The resolvedInUse variable insures only one disk
// resolution at time is running so the global level selectedDisks and resolvedDrives
// variables will not be corrupted.
ResolveLogicalPhysicalDisks resolveLogicalPhysicalDisks = new ResolveLogicalPhysicalDisks();
private volatile ManualResetEvent resolvedInUse = new ManualResetEvent(false);
private volatile int resolutionsScheduled = 0;
private ArrayList selectedDisks; //disks to search
//contains: string C:\, D:\, etc
//one letter designation per entry
//selectedDisks is initially set during form load byt the HandleDriveSelection() routine
//and will also be set by the disksToSearchButton_Click routine.
private ArrayList resolvedDrives;
//contains: string C;\, D:\;E:\, G:\ etc
//Each physical drive is represented by the letter designations of the
//partitions on the drive. Partitions on the same physical drive are
//within the same comma group.
//resolvedDrives is set in the ResolutionCompleted routine.
//--------------------------------------------------------------------------------------------------
// delegates used to call display functions from worker threads
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;
private delegate void DelegateUpdateStatus(String s);
private DelegateUpdateStatus m_DelegateUpdateStatus;
//--------------------------------------------------------------------------------------------------
// variables used for multithreading control
private object threadobj = new object(); //Thread control lock object
private List<Thread> searchThreads = new List<Thread>(); //Active search threads
private ManualResetEvent pleaseTerminate = new ManualResetEvent(false); //Set to true if the thread is to terminate early
private ManualResetEvent allThreadsTerminated = null; //used only when Form1 is closing
private delegate void TerminateThreads();
//--------------------------------------------------------------------------------------------------
private object syncobj = new object(); //local lock object for form displays
private int //statistics (update only when protected by lock(syncobj))
filesFound = 0,
directoriesFound = 0,
itemsFound = 0;
//fields to control BeginUpdate/EndUpdate for filesFoundBox
private DateTime
priorTime,
thisTime;
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;
private bool autoScrollMode = true; //list view scroll mode
private bool foldersOnlyDisplay; //type of grid that is in use
private bool performSequentialSearch = false; //sequentially search all disks
//--------------------------------------------------------------------------------------------------
Stopwatch elaspedTime = new Stopwatch(); //used to measure elasped search time
//batch interface fields
private NamedPipeClientStream pipe = null; //pipe is built if arguments were passed
public Form1()
{ InitializeComponent(); }
/// <summary>
/// Update the tool strip status line
/// </summary>
/// <param name="statusLine">single line message</param>
private void UpdateStatus(string statusLine)
{
try
{
if (this.InvokeRequired)
this.BeginInvoke(m_DelegateUpdateStatus, new Object[] { statusLine });
else
lock (syncobj)
toolStripStatusLabel1.Text = statusLine;
}
catch { }
} //ends private void UpdateStatus(...
/// <summary>
/// Writes one line to the list display. Will enter/exit filesFoundBox update mode
/// depending on message traffic per interval.
/// <para>High rates of message delivery caused unacceptable response times when attempting to stop
/// a scan or close the application.
/// </para>
/// <para>If more than MaxRate messages are delivered within MsgInterval milliseconds, then
/// MsgDisplayNolock will stop autoscroll and enter filesFoundBox.BeginUpdate() mode and start a timer to issue
/// a filesFoundBox.EndUpdate() call.
/// </para>
/// <para>When filesFoundBox enters the BeginUpdate() mode, the grid view is placed in
/// a BeginLoadData() mode. A pause interval is then calculated for timer1 based on the numer
/// of active threads plus 10 milliseconds. 'timer1' is started.
/// </para>
/// If the MaxRate * 2 is exceeded while in Begin/End update mode, pauses are issued to the
/// DiskScan routines.
/// <para>The timer1_Tick routine issues the EndUpdate() and EndLoadData() commands and restores autoscroll if necessary.
/// </para>
/// <para>A visual indicator of high message volume is given by continuing to display
/// the ITEMSFOUND message but not updating the form when the number of messages exceeds msgCountMax.
/// </para>
/// <para>All updates to the message traffic variables must be made while lock(syncobj) is in effect.
/// </para>
/// </summary>
/// <param name="msg">line to be written</param>
private int MsgDisplayNolock(String msg)
{ //Display a single line message without issuing a local lock(syncobj).
//This routine expects the caller to own the lock.
int pause = 0; //milliseconds disk scan should pause
listBox1.Items.Add(msg);
if (listBox1.Items.Count > MaxRate) //check pacing only when reporting a large number of items
switch (inUpdate)
{
case InUpdate.InUpdateNo:
if (autoScrollMode)
listBox1.TopIndex = listBox1.Items.Count - 1;
if (++msgsPerInterval > MaxRate) //check message traffic rate
{ //how long did it take to reach maximum number of messages per interval?
thisTime = DateTime.Now;
if ((thisTime.Millisecond - priorTime.Millisecond) <= MsgInterval)
{ //enter BeginUpdate mode
listBox1.BeginUpdate();
table.BeginLoadData();
inUpdate = InUpdate.InUpdateSpeed;
timer1.Interval = 10 + PauseValue * 2;
timer1.Enabled = true;
}
priorTime = thisTime;
fileCountLabel.Text = ITEMSFOUND + itemsFound.ToString("N0", CultureInfo.CurrentCulture);
msgsPerInterval = 0;
}
break;
case InUpdate.InUpdateSpeed:
if (++msgsPerInterval > MaxRate * 2)
{
inUpdate = InUpdate.InUpdatePausing; //enter pause mode
listBox1.EndUpdate();
table.EndLoadData();
}
break;
case InUpdate.InUpdatePausing:
fileCountLabel.Text = ITEMSFOUND + itemsFound.ToString("N0", CultureInfo.CurrentCulture);
pause = PauseValue;
break;
} //ends if (filesFoundBox.Items.Count > MaxRate)
else
{
fileCountLabel.Text = ITEMSFOUND + itemsFound.ToString("N0", CultureInfo.CurrentCulture);
if (autoScrollMode)
listBox1.TopIndex = listBox1.Items.Count - 1;
}
return pause;
} //ends private void MsgDisplayNolock
/// <summary>
/// Activated only if an "excessive" number of messages are being processed per time interval
/// </summary>
private void timer1_Tick(object sender, EventArgs e)
{
lock (syncobj)
{ //protect against concurrent updates of inUpdate and timers
switch (inUpdate)
{
case InUpdate.InUpdateNo:
break;
case InUpdate.InUpdateSpeed:
//exit BeginUpdate mode
listBox1.EndUpdate();
table.EndLoadData();
if (msgsPerInterval > MaxRate * 2)
inUpdate = InUpdate.InUpdatePausing; //enter pause mode
else if (msgsPerInterval < MaxRate)
{
timer1.Enabled = false;
inUpdate = InUpdate.InUpdateNo;
msgsPerInterval = 0;
priorTime = DateTime.Now;
}
if (autoScrollMode)
listBox1.TopIndex = listBox1.Items.Count - 1;
break;
case InUpdate.InUpdatePausing:
timer1.Enabled = false;
inUpdate = InUpdate.InUpdateNo;
msgsPerInterval = 0;
priorTime = DateTime.Now;
if (autoScrollMode)
listBox1.TopIndex = listBox1.Items.Count - 1;
break;
}
} //ends lock (syncobj)
} //ends private void timer1_Tick(...
/// <summary>
/// Send a single or multiple line message to the list view
/// </summary>
/// <param name="textLines">message(s) to be displayed</param>
private void SendMsg(string textLines)
{ //display multi-line messages
//may be driven by search threads
lock (syncobj)
{
while (textLines != null)
{
int ndx = textLines.IndexOf(Environment.NewLine);
if (ndx > -1)
{
MsgDisplayNolock(textLines.Substring(0, ndx));
if (ndx < textLines.Length)
{
textLines = textLines.Substring(ndx + 1);
if (Environment.NewLine == textLines.Substring(0, 1))
textLines = textLines.Substring(1);
}
else
textLines = null;
}
else
{
MsgDisplayNolock(textLines);
textLines = null;
}
} //ends while (textLines != null)
} //ends lock (syncobj)
} //ends private void SendMsg(...
/// <summary>
/// FileFind was activated with parameters. Output is being sent
/// to a pipe provided by the activator.
/// </summary>
/// <param name="msg">information to be displayed</param>
private void SendToPipe(string msg)
{
byte[] bytes = Encoding.Default.GetBytes(msg + "\n");
try { pipe.Write(bytes, 0, bytes.Length); }
catch { pleaseTerminate.Set(); }
}
/// <summary>
/// Called by DiskScan threads when a file matches search criteria
/// </summary>
/// <param name="fi">file to report on</param>
/// <param name="volumeId">volume file was found on</param>
/// <returns>pause interval if traffic is excessive</returns>
private int ReceiveFileInfo(FileInfo fi, string volumeId)
{ //add file information to the grid view
//Invoked by search threads
int pause = 0; //milliseconds disk scan should pause
lock (syncobj)
{
if (null == pipe)
{
string dir = fi.DirectoryName;
string disk = dir.Substring(0, dir.IndexOf(@"\") + 1);
dir = dir.Substring(disk.Length);
++filesFound;
++itemsFound;
pause = MsgDisplayNolock(fi.FullName); //update the list view
DataRow newRow = table.NewRow();
newRow[GTFILENAME] = fi.Name;
newRow[GTSIZE] = fi.Length;
newRow[GTDISK] = disk;
newRow[GTVOLUMEID] = volumeId;
newRow[GTDIRECTORY] = dir;
newRow[GTCREATED] = fi.CreationTime;
newRow[GTMODIFIED] = fi.LastWriteTime;
newRow[GTLASTACCESSED] = fi.LastAccessTime;
table.Rows.Add(newRow); //update the grid view
}
else
SendToPipe(fi.FullName);
} //ends lock(syncobj)
return pause;
} //ends private void ReceiveFileInfo(...
/// <summary>
/// Called by DiskScan threads when a folder matches search criteria
/// </summary>
/// <param name="dir">directory to report on</param>
/// <param name="volumeId">volume directory was found on</param>
/// <returns>pause interval if traffic is excessive</returns>
private int ReceiveDirInfo(DirectoryInfo dir, string volumeId)
{ //add directory information to the grid view
//Invoked by search threads
int pause = 0; //milliseconds disk scan should pause
lock (syncobj)
{
if (null == pipe)
{
string dirname = dir.FullName;
string disk = dirname.Substring(0, dirname.IndexOf(@"\") + 1);
dirname = dirname.Substring(disk.Length);
++directoriesFound;
++itemsFound;
pause = MsgDisplayNolock(dir.FullName); //update the list view
DataRow newRow = table.NewRow();
newRow[GTDISK] = disk;
newRow[GTVOLUMEID] = volumeId;
newRow[GTDIRECTORY] = dirname;
newRow[GTCREATED] = dir.CreationTime.ToString();
newRow[GTMODIFIED] = dir.LastWriteTime.ToString();
newRow[GTLASTACCESSED] = dir.LastAccessTime.ToString();
table.Rows.Add(newRow); //update the grid view
}
else
SendToPipe(dir.FullName);
} //ends lock(syncobj)
return pause;
} //ends private void ReceiveDirInfo(...
/// <summary>
/// Called when TerminateAllThreads() completes
/// </summary>
/// <param name="ar"></param>
private void TerminateThreadsCallback(IAsyncResult ar)
{
AsyncResult result = ar as AsyncResult;
TerminateThreads resolve = result.AsyncDelegate as TerminateThreads;
if (null != allThreadsTerminated)
allThreadsTerminated.Set();
resolve.EndInvoke(ar);
} //ends private void TerminateThreadsCallback(...
/// <summary>
/// Called asynchronusly when the user has requested all threads terminate or is closing the main form.
/// It is expected pleaseTerminate.Set(); has already been called.
/// </summary>
private void TerminateAllThreads()
{
int
alive,
waitCount = 0;
while (true)
{
do
{ //give threads a change to terminate gracefully
Thread.Sleep(200);
Application.DoEvents();
alive = 0;
lock (threadobj)
{
foreach (Thread workThread in searchThreads)
if (workThread.IsAlive)
++alive;
} //ends lock(threadobj)
} while ((alive > 0) && (++waitCount < 5));
alive = 0;
Application.DoEvents();
lock (threadobj)
{ //kill any threads that have not terminated gracefully
foreach (Thread workThread in searchThreads)
{
if (workThread.IsAlive)
{
++alive;
workThread.Abort();
}
}
} //ends lock(threadobj)
if (alive == 0)
break;
} //ends while (true)
} //ends private void TerminateAllThreads()
/// <summary>
/// Dynamic build of the grid view
/// </summary>
/// <param name="filesNeeded">Set to true if columns associated with files are to be built</param>
private void BuildGridTable(bool filesNeeded)
{ //create the grid table
if (null != table)
{
SaveCurrentColumns();
//already on the desired view?
if ((filesNeeded && usingView.ViewName == "FilesView")
|| (!filesNeeded && usingView.ViewName == "FoldersView"))
{
table.Clear(); //yes, just clear the table
return;
}
else
table = null; //no, switch to correct view
}
if (null == table)
{
gridView.DataSource = null; //release old table, if any
gridView.BackgroundColor = listBox1.BackColor;
gridView.BorderStyle = listBox1.BorderStyle;
table = new DataTable("FileFind");
if (filesNeeded)
{
table.Columns.Add(new DataColumn(GTFILENAME));
table.Columns.Add(new DataColumn(GTSIZE, Type.GetType("System.Int64")));
foldersOnlyDisplay = false;
}
else
foldersOnlyDisplay = true;
table.Columns.Add(new DataColumn(GTDISK));
table.Columns.Add(new DataColumn(GTVOLUMEID));
table.Columns.Add(new DataColumn(GTDIRECTORY));
table.Columns.Add(new DataColumn(GTCREATED, Type.GetType("System.DateTime")));
table.Columns.Add(new DataColumn(GTMODIFIED, Type.GetType("System.DateTime")));
table.Columns.Add(new DataColumn(GTLASTACCESSED, Type.GetType("System.DateTime")));
BindingSource bs = new BindingSource();
bs.DataSource = table;
gridView.DataSource = bs;
if (filesNeeded)
gridView.Columns[GTSIZE].DefaultCellStyle.Format = "N0";
gridView.Columns[GTCREATED].DefaultCellStyle.FormatProvider = CultureInfo.CurrentCulture;
gridView.Columns[GTMODIFIED].DefaultCellStyle.FormatProvider = CultureInfo.CurrentCulture;
gridView.Columns[GTLASTACCESSED].DefaultCellStyle.FormatProvider = CultureInfo.CurrentCulture;
}
ConfigInfo configInfo = new ConfigInfo();
if (filesNeeded)
{
if (null == (usingView = filesView))
{
usingView = filesView = configInfo.GetGridView("FilesView");
if (null == usingView)
usingView = filesView = BuildNewGridInfo("FilesView");
}
}
else
{
if (null == (usingView = foldersView))
{
usingView = foldersView = configInfo.GetGridView("FoldersView");
if (null == usingView)
usingView = foldersView = BuildNewGridInfo("FoldersView");
}
}
//You must rearrange the grid starting with the first displayed column and
//the grid must be visible otherwise the result is wrong.
bool holdVisible = gridView.Visible; //Columns will not reorder unless
gridView.Visible = true; //the grid is visible.
usingView.SortByDisplayOrder(); //Put columns in display order.
foreach (ColumnInfo columnInfo in usingView)
gridView.Columns[columnInfo.ColumnName].DisplayIndex = columnInfo.DisplayOrder;
gridView.Visible = holdVisible;
foreach (DataGridViewColumn dgc in gridView.Columns)
{
if (GTDISK == dgc.Name)
dgc.AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader;
else
dgc.MinimumWidth = dgc.Width / 2;
if (usingView.Contains(dgc.Name))
gridView.Columns[dgc.Name].Visible = usingView.Visible(dgc.Name);
}
foreach (ToolStripMenuItem menuItem in this.showGridColumnsToolStripMenuItem.DropDownItems)
{ //update the 'Show grid columns' menu items according to the states saved in the configInfo
if (usingView.Contains(menuItem.Text))
{
menuItem.Enabled = true;
menuItem.Checked = usingView.Visible(menuItem.Text);
}
else
menuItem.Enabled = false;
}
} //ends private void BuildGridTable(...
/// <summary>
/// Saves column ordering information for the current grid view
/// </summary>
private void SaveCurrentColumns()
{ //store current column display order
usingView.IsDirty = true;
DataGridViewColumnCollection columns = gridView.Columns; //displayable grid columns
for (int i = 0; i < columns.Count; ++i)
usingView.UpdateDisplayOrder(columns[i].Name, columns[i].DisplayIndex);
}
/// <summary>
/// Restores column display order
/// </summary>
/// <param name="name">View name</param>
/// <returns>grid view with unwanted columns disabled</returns>
private GridInfoCollection BuildNewGridInfo(string name)
{
DataGridViewColumnCollection columns = gridView.Columns; //displayable grid columns
GridInfoCollection newView = new GridInfoCollection(name);
for (int i = 0; i < columns.Count; ++i)
newView.Add(new ColumnInfo(columns[i].Name, true, columns[i].DisplayIndex, -1));
return newView;
}
private void BuildGridColumnSelectionMenu()
{ //build menu column selection
ArrayList toolStripMenuItems = new ArrayList();
toolStripMenuItems.Add(BuildMenuItem(GTFILENAME));
toolStripMenuItems.Add(BuildMenuItem(GTSIZE));
toolStripMenuItems.Add(BuildMenuItem(GTDISK));
toolStripMenuItems.Add(BuildMenuItem(GTVOLUMEID));
toolStripMenuItems.Add(BuildMenuItem(GTDIRECTORY));
toolStripMenuItems.Add(BuildMenuItem(GTCREATED));
toolStripMenuItems.Add(BuildMenuItem(GTMODIFIED));
toolStripMenuItems.Add(BuildMenuItem(GTLASTACCESSED));
System.Windows.Forms.ToolStripItem[] toolStripItems =
(System.Windows.Forms.ToolStripMenuItem[])toolStripMenuItems.ToArray(typeof(System.Windows.Forms.ToolStripMenuItem));
this.showGridColumnsToolStripMenuItem.DropDownItems.AddRange(toolStripItems);
} //ends private void BuildGridColumnSelectionMenu(...
private System.Windows.Forms.ToolStripMenuItem BuildMenuItem(string itemName)
{
System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem = new ToolStripMenuItem();
StringBuilder sb = new StringBuilder(128);
sb.Append(itemName.Trim());
sb.Replace(' ', '_');
fileToolStripMenuItem.Name = sb.ToString();
fileToolStripMenuItem.Text = itemName;
fileToolStripMenuItem.AutoSize =
fileToolStripMenuItem.Checked = true;
fileToolStripMenuItem.Enabled = false;
fileToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click);
return fileToolStripMenuItem;
} //ends private System.Windows.Forms.ToolStripMenuItem BuildMenuItem(...
private void ActivateListView()
{ //swap to "List View"
gridListViewButton.Text = MENUGRIDVIEW;
if (0 == listBox1.Items.Count)
sortOutputButton.Enabled = false;
else
sortOutputButton.Enabled = true;
gridView.Visible = false;
listBox1.Visible = true;
sortOutputButton.Text = SORTOUTPUT;
} //ends private void ActivateListView()
private void ActivateGridView()
{ //swap to "Grid View"
sortOutputButton.Text = DELETE;
gridListViewButton.Text = MENULISTVIEW;
if (0 == gridView.RowCount)
sortOutputButton.Enabled = false;
else
sortOutputButton.Enabled = true;
listBox1.Visible = false;
gridView.Visible = true;
gridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells);
//The above gridView.AutoResizeColumns may cause long pauses when large numbers of
//entries are in the gridView
} //ends private void ActivateGridView()
/// <summary>
/// Delete one or more data rows and the files or folders named in the rows
/// </summary>
private void UserRequestedDelete()
{
fileCountLabel.Text =
msgLabel1.Text =
msgLabel2.Text = "";
int itemsDeleted = 0;
DataGridViewSelectedRowCollection dgv = gridView.SelectedRows;
bool
hasFileNameTitle = false, //determine if the 'File name' column exists
foundReparsePoint = false;
foreach (DataColumn dc in table.Columns)
if (dc.ColumnName.ToString() == GTFILENAME)
{
hasFileNameTitle = true;
break;
}
table.BeginLoadData();
foreach (DataGridViewRow deleteRow in dgv)
{ //delete the selected file/directory
Int32 index = deleteRow.Index;
string dirName = Path.Combine(gridView.Rows[index].Cells[GTDISK].Value.ToString(),
gridView.Rows[index].Cells[GTDIRECTORY].Value.ToString());
string fname = "";
if(hasFileNameTitle)
fname = gridView.Rows[index].Cells[GTFILENAME].Value.ToString();
if (String.IsNullOrEmpty(fname))
{ //delete a directory
if (Directory.Exists(dirName))
{
DirectoryInfo processDirectory = new DirectoryInfo(dirName);
if ((processDirectory.Attributes & FileAttributes.ReparsePoint)
== FileAttributes.ReparsePoint)
foundReparsePoint = true;
try
{
FileSystem.DeleteDirectory(dirName,
UIOption.OnlyErrorDialogs,
RecycleOption.SendToRecycleBin);
listBox1.Items.Remove(dirName); //keep list & grid in sync
gridView.Rows.RemoveAt(index);
msgLabel1.Text = "Deleted " + dirName;
++itemsDeleted;
}
catch (Exception ex)
{ msgLabel1.Text = ex.Message; }
//remove listed members that were in the directory
string removedDirectory = dirName + "\\";
int i = 0;
Stack myStack = new Stack();
foreach (string listItem in listBox1.Items)
{
string displayedDirectory = listItem.ToString();
if (displayedDirectory.Length < removedDirectory.Length)
continue;
if (string.Compare(removedDirectory,
displayedDirectory.Substring(0, removedDirectory.Length),
true, CultureInfo.InvariantCulture) == 0)
myStack.Push(i);
++i;
}
listBox1.BeginUpdate();
try
{
while (true)
{
int j = (int)myStack.Pop();
listBox1.Items.RemoveAt(j);
}
}
catch (InvalidOperationException) { }
listBox1.EndUpdate();
for (int ndx = 0; ndx <= gridView.Rows.Count - 1; ++ndx)
{
string displayedDirectory = Path.Combine(gridView.Rows[ndx].Cells[GTDISK].Value.ToString(),
gridView.Rows[ndx].Cells[GTDIRECTORY].Value.ToString());
displayedDirectory += "\\";
if (displayedDirectory.Length < removedDirectory.Length)
continue;
if (string.Compare(removedDirectory,
displayedDirectory.Substring(0, removedDirectory.Length),
true, CultureInfo.InvariantCulture) == 0)
myStack.Push(ndx);
}
try
{
while (true)
{
int j = (int)myStack.Pop();
gridView.Rows.RemoveAt(j);
}
}
catch (InvalidOperationException) { }
} //ends if (Directory.Exists(...
}
else
{ //delete a file
string fileFullName = Path.Combine(dirName, fname);
if (File.Exists(fileFullName))
{
try
{
FileSystem.DeleteFile(fileFullName,
UIOption.OnlyErrorDialogs,
RecycleOption.SendToRecycleBin);
listBox1.Items.Remove(fileFullName); //keep list & grid in sync
gridView.Rows.RemoveAt(index);
msgLabel1.Text = "Deleted " + fileFullName;
++itemsDeleted;
}
catch (Exception ex)
{ msgLabel1.Text = ex.Message; }
}
}
} //ends foreach (DataGridViewRow deleteRow...
table.EndLoadData();
fileCountLabel.Text = itemsDeleted.ToString("N0", CultureInfo.CurrentCulture) + " items deleted";
if (foundReparsePoint)
msgLabel2.Text = "Use Computer Manage function to remove reparse points";
} //ends private void UserRequestedDelete()
private void Form1_Load(object sender, EventArgs e)
{ // initialize delegates
m_DelegateSendMsg = new DelegateSendMsg(this.SendMsg);
m_DelegateThreadStopped = new DelegateThreadStopped(this.ThreadStopped);
m_SendFileInfo = new SendFileInfo(this.ReceiveFileInfo);
m_SendDirectoryInfo = new SendDirectoryInfo(this.ReceiveDirInfo);
m_DelegateUpdateStatus = new DelegateUpdateStatus(this.UpdateStatus);
//acquire configuration information
ConfigInfo configInfo = new ConfigInfo();
if (null == configInfo.UseFont) //prior font in use?
configInfo.UseFont = this.Font; // no, save current font
else
this.Font = configInfo.UseFont; // yes, change to the prior font
toolStripStatusLabel1.Text = "";
//setup filter list constraints
FilterList usingFilterList = null;
try { usingFilterList = configInfo.ActiveFilterList; }
catch { }
HandleDriveSelection(); //starts async drive resolution
if (null != usingFilterList)
filterLabel.Text = "Using filter list " + usingFilterList.Name;
else
filterLabel.Text = "No filter list";
VolumeLabelDrive volumeLabels = new VolumeLabelDrive();
if (volumeLabels.HasDuplicates || volumeLabels.HasUnlabeledVolumes)
if (volumeLabels.HasDuplicates && volumeLabels.HasUnlabeledVolumes)
filterLabel.Text += "; Caution: unlabeled drives or duplicate volume labels were found";
else if (volumeLabels.HasDuplicates)
filterLabel.Text += "; Caution: duplicate volume labels were found";
else if (volumeLabels.HasUnlabeledVolumes)
filterLabel.Text += "; Caution: unlabeled drives were found";
//provide initial instructions and complete the initial form
fileCountLabel.Text = "Enter one or more masks to search for file and/or folder names.";
msgLabel1.Text = "Use '?' to match any single character. Use '*' to match one or more characters.";
msgLabel2.Text = "";
//set prior menu values
showHiddenFoldersfilesToolStripMenuItem.Checked = configInfo.ShowHiddenFoldersFiles;
scanningViaEnumeratorToolStripMenuItem.Checked = configInfo.ScanningViaEnumerator;
autoScrollMode =
autoScrollingToolStripMenuItem.Checked = configInfo.AutoScrolling;
BuildGridColumnSelectionMenu(); //add available columns to menu bar
BuildGridTable(true);
gridView.Bounds = listBox1.Bounds; //make list and grid viewing areas the same
if (configInfo.StartWithGrid)
{
this.Width += this.Width / 4; //increase form width by 25%
ActivateGridView();
msgLabel2.Text = "Double click file name to launch file or directory name to open folder.";
}
else
{
ActivateListView();
msgLabel2.Text = "Double click name to launch file or open folder.";
}
startStopButton.Enabled = false;
Application.Idle += new System.EventHandler(OnIdle);
fileNameBox.Select(); //put focus to fileNameBox
priorTime = DateTime.Now;
dateTimeInfo = new DateTimeInfo();
if (0 != Program.parametersReceived.Length)
{ //parameters were passed to this program
//validate the parameters and connect to a pipe for output
string filterListName = "";
string pipeName = "";
string masks = "";
string serverName = ".";
bool showForm = false;
foreach (string str in Program.parametersReceived)
if (str.StartsWith("-FilterList:", StringComparison.InvariantCultureIgnoreCase))
filterListName = str.Substring("-FilterList:".Length);
else if (str.StartsWith("-PipeName:", StringComparison.InvariantCultureIgnoreCase))
pipeName = str.Substring("-PipeName:".Length);
else if (str.StartsWith("-Masks:", StringComparison.InvariantCultureIgnoreCase))
masks = str.Substring("-Masks:".Length);
else if (str.StartsWith("-FilesFolders:"))
{
string searchingFor = str.Substring("-FilesFolders:".Length).ToLower(CultureInfo.InvariantCulture);
switch (searchingFor)
{
case "files":
filesOnlyRadioButton.Checked = true;
break;
case "folders":
foldersOnlyRadioButton.Checked = true;
break;
case "both":
filesAndFoldersRadioButton.Checked = true;
break;
}
}
else if (str.StartsWith("-Visible:", StringComparison.InvariantCultureIgnoreCase))
showForm = (0 == String.Compare(str.Substring("-Visible:".Length), "Yes",
true, CultureInfo.InvariantCulture));
if (!String.IsNullOrEmpty(pipeName)
&& !String.IsNullOrEmpty(masks))
{
if (!String.IsNullOrEmpty(filterListName))
{
FilterListCollection filterLists;
if (null != (filterLists = configInfo.MasterFilterListCollection))
{
FilterList filterList = filterLists.LocateFilterList(filterListName);
if (null != filterList)
{
configInfo.ActiveFilterList = filterList;
filterLabel.Text = "Using filter list " + filterList.Name;
}
else
{
fileCountLabel.Text = "Could not find filter list " + filterListName;
filterLabel.Text = "No filter list is being used";
showForm = true;
}
}
}
msgLabel1.Text = "-FilterList:" + filterListName;
msgLabel2.Text = "-PipeName:" + pipeName;
fileNameBox.Text = masks;
UpdateStatus("Connecting to " + pipeName);
Application.DoEvents();
pipe = new NamedPipeClientStream(serverName, pipeName, PipeDirection.Out, PipeOptions.None);
try { pipe.Connect(3000); }
catch (TimeoutException)
{ fileCountLabel.Text = "Connection timed out for pipe " + pipeName; }
if (pipe.IsConnected && pipe.CanWrite)
{ //pipe connection is valid
gridListViewButton.Enabled =
filesAndFoldersRadioButton.Enabled =
foldersOnlyRadioButton.Enabled =
filesOnlyRadioButton.Enabled = false;
UpdateStatus("Pipe connection established");
fileCountLabel.Text = "Connected to pipe " + pipeName;
startStopButton.Enabled =
this.ShowInTaskbar =
this.Visible = showForm;
Application.DoEvents(); //allow form to display
StartSearching();
}
else
{ //pipe connection failed
try
{ pipe.Close(); }
catch { }
this.Close(); //close the FileFind application
}
}
else
{
msgLabel1.Text = "-FilterList:" + filterListName;
msgLabel2.Text = "-PipeName:" + pipeName;
fileNameBox.Text = masks;
fileCountLabel.Text = "Invalid arguments were received at startup";
}
}
} //ends private void Form1_Load(...
/// <summary>
/// Enables the Start/Stop button only after a mask has been entered
/// </summary>
private void OnIdle(Object sender, EventArgs e)
{ startStopButton.Enabled = fileNameBox.Text.Length > 0; }
private void Form1_Closing(object sender, FormClosingEventArgs e)
{ // Request termination of any active threads.
// Store the current view in the ConfigInfo object
//and save the configuration data for the next time this application is run.
// Abort any threads still running.
Application.Idle -= new System.EventHandler(OnIdle);
timer1.Enabled = false;
allThreadsTerminated = new ManualResetEvent(false);
pleaseTerminate.Set(); //request threads stop
startStopButton.Text = SEARCHSTOPPING;
//save information needed for next execution
ConfigInfo configInfo = new ConfigInfo();
if (MENULISTVIEW == gridListViewButton.Text)
configInfo.StartWithGrid = true;
else
configInfo.StartWithGrid = false;
if (null != usingView)
{
SaveCurrentColumns();
if (null != filesView && filesView.IsDirty)
configInfo.StoreGridView(filesView);
if (null != foldersView && foldersView.IsDirty)
configInfo.StoreGridView(foldersView);
}
configInfo.SaveConfig();
Application.DoEvents();
if (0 != searchThreads.Count)
{ //some threads are still active
TerminateThreads terminateThreads = new TerminateThreads(TerminateAllThreads);
terminateThreads.BeginInvoke(new AsyncCallback(TerminateThreadsCallback), null);
while(allThreadsTerminated.WaitOne(200, false))
Application.DoEvents();
} //ends if (0 != searchThreads.Count)
if (null != pipe)
{ //need to close the pipe
try { pipe.Close(); }
catch { }
}
} //ends private void Form1_Closing(...
/// <summary>
/// Enable or disable various buttons
/// </summary>
/// <param name="setting">Set to true to enable, false to disable</param>
private void SearchingButtons(bool setting)
{ //enable or disable various buttons and menu selections
if (null != pipe)
return;
listBox1.Sorted =
timeRangeButton.Enabled =
disksToSearchButton.Enabled =
FilterButton.Enabled =
fileNameBox.Enabled =
startStopButton.Enabled =
sortOutputButton.Enabled =
sequentialSearchToolStripMenuItem.Enabled = setting;
}
/// <summary>
/// StartSearching will start a thread for each selected disk.
/// The DiskScan thread will search the disks for matching files and directory nodes
/// </summary>
private void StartSearching()
{ //insure a mask has been provided
//reset statistics
//start a thread for each selected disk to search for matching files/directories
if (null == pipe)
{ //clear text messages
msgLabel1.Text =
msgLabel2.Text =
fileCountLabel.Text = "";
SearchingButtons(false);
}
WaitForResolvedCompletion();
string fileMasks = fileNameBox.Text.Trim(); //remove leading and trailing white space
if (String.IsNullOrEmpty(fileMasks))
{
ConfigInfo configInfo = new ConfigInfo();
MessageBox.Show("You must enter one or more search masks", Application.ProductName,
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
SearchingButtons(true);
return;
}
//for each disk set, start a thread to search disks for files and/or folders matching the mask(s)
if (0 == resolvedDrives.Count)
msgLabel2.Text = "No disks were selected for searching";
else
lock (threadobj)
{ //lock prevents concurrent update of searchThreads until all threads are started
itemsFound = //reset statistics
directoriesFound =
filesFound = 0;
priorTime = DateTime.Now; //for messages per interval measurements
listBox1.Items.Clear(); //clear the list view data
table.Clear(); //clear the grid view data
pleaseTerminate.Reset(); //insure threads are enabled to run status
if (foldersOnlyRadioButton.Checked)
BuildGridTable(false); //drop file name and size grid columns
else
BuildGridTable(true); //display all grid columns
startStopButton.Text = STOPSEARCH;
searchThreads = new List<Thread>(resolvedDrives.Count); // + networkPaths.Count);
elaspedTime.Reset();
elaspedTime.Start();
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...
startStopButton.Enabled = true;
BuildThreadStatusLine();
} //ends lock (threadobj)
} //ends StartSearching()
private void HandleDriveSelection()
{ //populate the list of disks to search
//output is saved to global 'selectedDisks'
//An asynchronous disk resolution is started by this routine
int diskCount = 0;
ArrayList localSelectedDisks = FetchAllDisks(out diskCount);
switch (diskCount)
{
case -1:
disksToSearchButton.Text = SEARCHALLDISKS;
break;
case 0:
disksToSearchButton.Text = SEARCHNONE;
break;
default:
disksToSearchButton.Text = SEARCHSELECTEDDISKS;
break;
}
if (0 == localSelectedDisks.Count)
msgLabel2.Text = "Unable to find any disks on this system";
selectedDisks = localSelectedDisks;
} //ends private void HandleDriveSelection()
/// <summary>
/// fetchs all logical ready drives on the system
/// and starts logical to physical resolution
/// </summary>
/// <param name="diskCount">
/// Returns number of drives selected else -1 then all ready disks have been selected.</param>
/// <returns>returns an array of the names of logical drives on the system</returns>
private ArrayList FetchAllDisks(out int diskCount)
{
ConfigInfo configInfo = new ConfigInfo();
ArrayList selected = configInfo.SelectAllDisks(out diskCount);
StartResolution(selected);
return selected;
} //ends private ArrayList FetchAllDisks(...
/// <summary>
/// fetchs an array of logical drives to be searched
/// and starts logical to physical resolution
/// </summary>
/// <returns>returns an array of the names of logical drives to be searched</returns>
private ArrayList FetchSelectedDisks(ArrayList selected)
{
StartResolution(selected);
return selected;
}//ends private ArrayList FetchSelectedDisks()
/// <summary>
/// Starts an async thread to assign logical disk partitions to physical drives
/// </summary>
/// <param name="selected">names of logical drives to resolve</param>
private void StartResolution(ArrayList selected)
{
//wait for any other drive resolution threads to complete
Interlocked.Increment(ref resolutionsScheduled);
if (resolvedInUse.WaitOne(0, true))
{
this.Cursor = Cursors.WaitCursor;
UpdateStatus("Waiting on logical/physical drive resolution");
resolvedInUse.WaitOne();
this.Cursor = Cursors.Default;
}
resolvedInUse.Set();
UpdateStatus("Starting logical/physical disk resolution");
resolveLogicalPhysicalDisks.BeginResolveDrives(selected, ResolutionCompleted);
} //ends private void StartResolution()
private void ResolutionCompleted(ArrayList drives)
{ //Caution: runs asynchronously under the resolveLogicalPhysicalDisks Callback thread
//results are stored in global 'resolvedDrives'
resolvedDrives = drives;
if (performSequentialSearch)
{ //assign all drives to the same DiskScan thread
string[] resolvedDrivesArray = (string[])resolvedDrives.ToArray(typeof(string));
resolvedDrives = new ArrayList();
resolvedDrives.Add(String.Join(";", resolvedDrivesArray));
}
//disk resolution has completed, display resolution information
StringBuilder sb = new StringBuilder(128);
foreach (string diskset in resolvedDrives)
{
if (diskset.Length > 3)
sb.Append(" (" + diskset + ")");
else
sb.Append(" " + diskset);
}
//if (0 != networkPathCount)
// sb.Append(" " +networkPathCount.ToString("n0", CultureInfo.CurrentCulture) + " net paths");
UpdateStatus("Resolved " + sb.ToString());
Interlocked.Decrement(ref resolutionsScheduled);
resolvedInUse.Reset();
}
/// <summary>
/// Waits for disk resolution completion
/// </summary>
private void WaitForResolvedCompletion()
{
if (!resolveLogicalPhysicalDisks.ResolutionComplete)
do
{
this.Cursor = Cursors.WaitCursor;
UpdateStatus("Waiting on logical/physical drive resolution");
resolveLogicalPhysicalDisks.ResolveEvent.WaitOne();
this.Cursor = Cursors.Default;
} while (0 != resolutionsScheduled);
} //ends private void WaitForResolvedCompletion()
/// <summary>
/// Called asynchronously when a thread terminates. Removes the thread from the
/// searchThreads ArrayList and, if no active tasks are running, reports
/// search completion and enables appropriate buttons.
/// Also updates the status line.
/// </summary>
/// <param name="threadName">name of terminating thread</param>
private void ThreadStopped(string threadName)
{ //Invoked by a thread just before it terminates
lock (threadobj)
{
int ndx = 0;
foreach (Thread searchThread in searchThreads)
if (searchThread.Name == threadName)
{
searchThreads.RemoveAt(ndx);
break;
}
else
++ndx;
if (0 == searchThreads.Count)
{ //all threads have completed, report stats & enable buttons
elaspedTime.Stop();
if (null != pipe)
{ //Running with a pipe, stop the FileFind program
try { pipe.Close(); } //close the pipe
catch { }
this.Close(); //close the FileFind application
}
else
{
if (autoScrollMode)
listBox1.TopIndex = listBox1.Items.Count - 1;
if (filesAndFoldersRadioButton.Checked)
fileCountLabel.Text = ITEMSFOUND + itemsFound.ToString("N0", CultureInfo.CurrentCulture)
+ " ( " + filesFound.ToString("N0", CultureInfo.CurrentCulture) + " files and "
+ directoriesFound.ToString("N0", CultureInfo.CurrentCulture) + " directories )";
else
fileCountLabel.Text = ITEMSFOUND + itemsFound.ToString("N0", CultureInfo.CurrentCulture);
timeRangeButton.Enabled =
disksToSearchButton.Enabled =
FilterButton.Enabled =
fileNameBox.Enabled = true;
gridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
if (gridView.Visible && (gridView.RowCount > 0))
sortOutputButton.Enabled = true;
else if (listBox1.Items.Count > 0)
sortOutputButton.Enabled = true;
if (pleaseTerminate.WaitOne(0, true))
UpdateStatus("Termination request completed, search time: "
+ elaspedTime.Elapsed.ToString());
else
UpdateStatus("Search completed, search time: "
+ elaspedTime.Elapsed.ToString());
startStopButton.Text = STARTSEARCH;
}
}
else
BuildThreadStatusLine();
} //ends lock (threadobj)
} //ends private void ThreadStopped(...
/// <summary>
/// Builds and updates the status line. Caller must own a lock on threadobj.
/// </summary>
private void BuildThreadStatusLine()
{
//int networkPathCount = 0; //number of network paths being searched
StringBuilder sb = new StringBuilder(128);
foreach (Thread searchThread in searchThreads)
{
if (searchThread.Name.Length > 3)
sb.Append(" (" + searchThread.Name + ")"); //multi-partition drive
else
sb.Append(" " + searchThread.Name); //single drive
}
//if (0 != networkPathCount)
// sb.Append(" " + networkPathCount.ToString("n0", CultureInfo.CurrentCulture) + " net paths");
UpdateStatus("Searching " + searchThreads.Count + " disks: " + sb.ToString());
} //ends private void BuildThreadStatusLine()
#region Mouse click processing
private void GetFileStats(FileInfo fileInfo)
{ //gather and display information about a selected file
System.Text.StringBuilder sb = new System.Text.StringBuilder(256);
if ((fileInfo.Attributes & FileAttributes.Compressed) == FileAttributes.Compressed)
ReportAttributes(ref sb, "Compressed");
if ((fileInfo.Attributes & FileAttributes.Encrypted) == FileAttributes.Encrypted)
ReportAttributes(ref sb, "Encrypted");
if ((fileInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
ReportAttributes(ref sb, "Hidden");
if ((fileInfo.Attributes & FileAttributes.Offline) == FileAttributes.Offline)
ReportAttributes(ref sb, "Offline");
if ((fileInfo.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
ReportAttributes(ref sb, "ReadOnly");
if ((fileInfo.Attributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint)
ReportAttributes(ref sb, "ReparsePoint");
if ((fileInfo.Attributes & FileAttributes.System) == FileAttributes.System)
ReportAttributes(ref sb, "System");
if ((fileInfo.Attributes & FileAttributes.SparseFile) == FileAttributes.SparseFile)
ReportAttributes(ref sb, "SparseFile");
if (!String.IsNullOrEmpty(sb.ToString()))
sb.Append(" )");
msgLabel1.Text = "File size: "
+ NumericScaling.DisplayScaledNamesBytes(fileInfo.Length)
+ sb.ToString();
msgLabel2.Text = "Created: " + fileInfo.CreationTime;
} // ends GetFileStats(...
private void GetFolderStats(FileInfo fileInfo)
{ //gather and display information about a selected folder
string dirStats = null;
DirectoryInfo dirInfo = new DirectoryInfo(fileInfo.FullName);
if (dirInfo.Exists)
{
long files = 0;
long directories = 0;
// Call the GetFileSystemInfos method.
FileSystemInfo[] infos = dirInfo.GetFileSystemInfos();
try
{
foreach (FileSystemInfo fileSystemInfo in infos)
{
if (fileSystemInfo is DirectoryInfo) // is this is a DirectoryInfo object?
++directories;
else if (fileSystemInfo is FileInfo) // is this is a FileInfo object?
++files;
}
}
catch (Exception ex)
{ msgLabel1.Text = ex.Message; msgLabel2.Text = null; }
if (0 == (directories + files))
dirStats = " ( Empty )";
else
dirStats = " contains " + files.ToString("N0", CultureInfo.CurrentCulture) + " files and "
+ directories.ToString("N0", CultureInfo.CurrentCulture) + " folders";
} //ends if(dirInfo.Exists)
System.Text.StringBuilder sb = new System.Text.StringBuilder(128);
if ((dirInfo.Attributes & FileAttributes.Compressed) == FileAttributes.Compressed)
ReportAttributes(ref sb, "Compressed");
if ((dirInfo.Attributes & FileAttributes.Encrypted) == FileAttributes.Encrypted)
ReportAttributes(ref sb, "Encrypted");
if ((dirInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
ReportAttributes(ref sb, "Hidden");
if ((dirInfo.Attributes & FileAttributes.Offline) == FileAttributes.Offline)
ReportAttributes(ref sb, "Offline");
if ((dirInfo.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
ReportAttributes(ref sb, "ReadOnly");
if ((dirInfo.Attributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint)
ReportAttributes(ref sb, "ReparsePoint");
if ((dirInfo.Attributes & FileAttributes.System) == FileAttributes.System)
ReportAttributes(ref sb, "System");
if (!String.IsNullOrEmpty(sb.ToString()))
sb.Append(" )");
msgLabel1.Text = "Folder" + dirStats
+ sb.ToString();
msgLabel2.Text = "Created: " + fileInfo.CreationTime;
} //ends private void GetFolderStats(...
private void ReportAttributes(ref StringBuilder sb, string str)
{ //Used by GetFileStats and GetFolderStats
if (String.IsNullOrEmpty(sb.ToString()))
sb.Append(" (");
sb.Append(" " + str);
} //ends private void ReportAttributes(...
private void FileLaunch(object sender, MouseEventArgs e)
{ //a listBox item was double clicked
//get the selected item and launch the program or open the folder or disk volume
string str;
try { str = listBox1.SelectedItem.ToString(); }
catch (NullReferenceException)
{ return; }
try
{
FileInfo fileInfo = new FileInfo(str);
if ((fileInfo.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
GetFolderStats(fileInfo);
else
GetFileStats(fileInfo);
if (!PerformLaunch(fileInfo.FullName))
msgLabel1.Text = "Unable to launch " + fileInfo.FullName;
}
catch (Exception ex)
{ msgLabel1.Text = ex.Message; msgLabel2.Text = null; }
} //ends private void FileLaunch(...
private bool PerformLaunch(string parm)
{ //start a process using the parameter as a command line
bool PerformLaunch_result = true;
try
{
Process p = new Process();
p.StartInfo.FileName = parm;
p.StartInfo.Arguments = null;
p.Start();
}
catch (Exception ex)
{
string str = "Launch failed for\n" + parm + "\n"
+ ex.Message;
ConfigInfo configInfo = new ConfigInfo();
MessageBox.Show(str, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
PerformLaunch_result = false;
}
return PerformLaunch_result;
} //ends private bool PerformLaunch
/// <summary>
/// Display file or directory information in the message area
/// </summary>
private void FilesFoundBox_MouseClick(object sender, MouseEventArgs e)
{ //single mouse click in listBox
//determine if file or folder and report appropriate stats
string str;
try
{ str = listBox1.SelectedItem.ToString(); }
catch (NullReferenceException)
{ return; }
if ((!Directory.Exists(str)) && (!File.Exists(str)))
{
msgLabel1.Text = "File or directory not found";
msgLabel2.Text = null;
return;
}
try
{
FileInfo fileInfo = new FileInfo(str);
if ((fileInfo.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
GetFolderStats(fileInfo);
else
GetFileStats(fileInfo);
}
catch (Exception ex)
{ msgLabel1.Text = ex.Message; msgLabel2.Text = null; }
} //ends private void FilesFoundBox_MouseClick
/// <summary>
/// Display drive information in the message area
/// </summary>
/// <param name="diskName">name of disk</param>
private void DisplayDriveInfo(string diskName)
{
fileCountLabel.Text = "";
DriveInfo driveInfo = new DriveInfo(diskName);
if (driveInfo.IsReady)
{
msgLabel1.Text = diskName + " " + driveInfo.VolumeLabel
+ " Drive format: " + driveInfo.DriveFormat
+ " Drive type: " + driveInfo.DriveType;
long availableFreeSpace = driveInfo.AvailableFreeSpace;
long totalSize = driveInfo.TotalSize;
msgLabel2.Text = "Available space: " + NumericScaling.DisplayScaledNames(availableFreeSpace)
+ " Total size: " + NumericScaling.DisplayScaledNames(totalSize);
}
else
{
msgLabel1.Text = diskName + " is not ready";
msgLabel2.Text = "";
}
} //ends private void DisplayDriveInfo(...
private void CellContentClicked(object sender, DataGridViewCellEventArgs e)
{ //single mouse click in gridView
//determine if file or folder and report appropriate stats
if (-1 == e.RowIndex) //was title selected?
return; // yes
fileCountLabel.Text = "";
List<string> columnTitles = new List<string>(table.Columns.Count); //array of string containing column names
foreach (DataColumn dc in table.Columns)
columnTitles.Add(dc.ColumnName.ToString());
DisplayFileFolderInfo(columnTitles[e.ColumnIndex].ToString(), e.RowIndex);
} //ends private void CellContentClicked(...
private void CellContentDoubleClicked(object sender, DataGridViewCellEventArgs e)
{ //double mouse click in gridView
//determine if file or folder and launch appropriately
if (-1 == e.RowIndex) //was title selected?
return; // yes, ignore it
fileCountLabel.Text = "";
List<string> columnTitles = new List<string>(table.Columns.Count); //array of string containing column names
foreach (DataColumn dc in table.Columns) //populate the array
columnTitles.Add(dc.ColumnName.ToString());
FileFolderLaunch(columnTitles[e.ColumnIndex].ToString(), e.RowIndex);
} //ends private void CellContentDoubleClicked(...
#endregion Mouse click processing
#region Button processing
private void startStopButton_Click(object sender, EventArgs e)
{ //display verbage toggles between Start Search and Stop Search
//Start or stop the search threads
lock (threadobj)
{
if (STOPSEARCH == startStopButton.Text)
{
pleaseTerminate.Set();
startStopButton.Text = SEARCHSTOPPING;
}
else if (SEARCHSTOPPING == startStopButton.Text)
{
pleaseTerminate.Set();
TerminateThreads terminateThreads = new TerminateThreads(TerminateAllThreads);
terminateThreads.BeginInvoke(new AsyncCallback(TerminateThreadsCallback), null);
}
else
StartSearching();
} //ends lock (threadobj)
}
private void sortOutputButton_Click(object sender, EventArgs e)
{ //toggled between Sort Output in List View and Delete in grid view
if (sortOutputButton.Text == DELETE)
UserRequestedDelete();
else
{
this.Cursor = Cursors.WaitCursor;
listBox1.Sorted = true;
this.Cursor = Cursors.Default;
}
}
private void disksToSearchButton_Click(object sender, EventArgs e)
{ //Display a form to allow the user to select the disks to be searched
using (SelectDisksToSearch diskSelection = new SelectDisksToSearch(selectedDisks))
{
diskSelection.FormLocation = this.Location;
diskSelection.ShowDialog();
if (DialogResult.Cancel != diskSelection.DialogResult)
{
switch (diskSelection.DialogResult)
{
case DialogResult.Abort: //no drives were selected
MessageBox.Show("No disks were selected", Application.ProductName,
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
selectedDisks = new ArrayList();
disksToSearchButton.Text = SEARCHNONE;
break;
case DialogResult.Yes: //All drives were selected
disksToSearchButton.Text = SEARCHALLDISKS;
selectedDisks = FetchSelectedDisks(diskSelection.SelectedDisks);
break;
case DialogResult.No: //some drives were selected
disksToSearchButton.Text = SEARCHSELECTEDDISKS;
selectedDisks = FetchSelectedDisks(diskSelection.SelectedDisks);
break;
default:
MessageBox.Show("Unknown Dialog result for disk selection", Application.ProductName,
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
break;
}
StringBuilder sb = new StringBuilder(256);
sb.Append("Searching disks:");
foreach (String diskletter in selectedDisks)
sb.Append(" " + diskletter);
fileCountLabel.Text =
msgLabel1.Text = "";
msgLabel2.Text = sb.ToString();
}
}
} //ends private void disksToSearchButton_Click(...
private void FileNameBoxKeyPressed(object sender, KeyPressEventArgs e)
{ //key was pressed while focus was in FileNameBox
if ((char)Keys.Enter == e.KeyChar)
{ //treat as Search button
e.Handled = true;
StartSearching();
fileNameBox.Focus();
}
}
private void timeRangeButton_Click(object sender, EventArgs e)
{ //Display a form allowing user to select time ranges
using (SelectDateTimeRange selectDateTimeRange = new SelectDateTimeRange())
{
selectDateTimeRange.FormLocation = this.Location;
selectDateTimeRange.SelectedDateTimeRange = (DateTimeInfo)dateTimeInfo.Clone();
DialogResult dateTimeRangeResult = selectDateTimeRange.ShowDialog();
if (DialogResult.OK == dateTimeRangeResult)
dateTimeInfo = selectDateTimeRange.SelectedDateTimeRange;
}
DateTime fromDateTime = dateTimeInfo.IFromDateTime;
DateTime toDateTime = dateTimeInfo.IToDateTime;
msgLabel1.Text =
msgLabel2.Text =
fileCountLabel.Text = "";
if (dateTimeInfo.IDateTimeRange == DateTimeInfo.DateTimeRangeSearch.DateTimeRangeOff)
timeRangeButton.Text = SELECTTIMERANGE;
else
{ //display selected times in message area
timeRangeButton.Text = SELECTEDTIMERANGE;
msgLabel1.Text = "Selection time range is "
+ fromDateTime.ToShortDateString()
+ " " + fromDateTime.ToShortTimeString()
+ " to " + toDateTime.ToShortDateString()
+ " " + toDateTime.ToShortTimeString();
}
} //ends private void timeRangeButton_Click(...
private void gridListViewButton_Click(object sender, EventArgs e)
{ //switch between list and grid views
if (MENULISTVIEW == gridListViewButton.Text)
ActivateListView();
else
{
this.Cursor = Cursors.WaitCursor;
ActivateGridView();
this.Cursor = Cursors.Default;
}
}
/// <summary>
/// Launches a form to display the names of filters lists available.
/// Filter lists consist of drives, paths and/or folders to search or ignore during a search.
/// </summary>
private void FilterButton_Click(object sender, EventArgs e)
{
Application.Idle -= new System.EventHandler(OnIdle);
using (SelectFilterList diskFileFilters = new SelectFilterList())
{
diskFileFilters.FormLocation = this.Location;
diskFileFilters.ShowDialog();
if (DialogResult.OK == diskFileFilters.DialogResult)
{
ConfigInfo configInfo = new ConfigInfo();
selectedDisks = configInfo.FilterSelectedDisks(selectedDisks);
HandleDriveSelection();
msgLabel1.Text =
msgLabel2.Text = "";
FilterList filterList = configInfo.ActiveFilterList;
if (null != filterList)
filterLabel.Text = "Using filter list " + filterList.Name;
else
filterLabel.Text = "No filter list is being used";
}
}
fileNameBox.Focus();
Application.Idle += new System.EventHandler(OnIdle);
} //ends private void FilterButton_Click(...
#endregion Button processing
private void DisplayFileFolderInfo(string columnName, int row)
{ //display file, folder or disk volume info in the message area
switch (columnName)
{
case GTFILENAME:
case GTDIRECTORY:
break;
case GTDISK:
case GTVOLUMEID:
DisplayDriveInfo(gridView[GTDISK, row].Value.ToString());
return;
default:
return;
}
string fileFullName = "";
if (foldersOnlyDisplay)
{
fileFullName = Path.Combine(gridView[GTDISK, row].Value.ToString(),
gridView[GTDIRECTORY, row].Value.ToString());
if (!Directory.Exists(fileFullName))
{
msgLabel1.Text = "Directory not found";
msgLabel2.Text = null;
return;
}
}
else
{
string fileName = gridView[GTFILENAME, row].Value.ToString();
if ((String.IsNullOrEmpty(fileName.Trim()))
|| (GTDIRECTORY == columnName))
{
fileFullName = Path.Combine(
gridView[GTDISK, row].Value.ToString(),
gridView[GTDIRECTORY, row].Value.ToString());
try
{
if (!Directory.Exists(fileFullName))
{
msgLabel1.Text = "Directory not found";
msgLabel2.Text = null;
return;
}
}
catch (Exception ex)
{
msgLabel1.Text = "Access to directory is denied";
msgLabel2.Text = ex.Message;
return;
}
}
else
{
fileFullName = Path.Combine(
Path.Combine(gridView[GTDISK, row].Value.ToString(),
gridView[GTDIRECTORY, row].Value.ToString()),
gridView[GTFILENAME, row].Value.ToString());
try
{
if (!File.Exists(fileFullName))
{
msgLabel1.Text = "File not found";
msgLabel2.Text = null;
return;
}
}
catch (Exception ex)
{
msgLabel1.Text = "Access to file is denied";
msgLabel2.Text = ex.Message;
return;
}
}
}
try
{
FileInfo fileInfo = new FileInfo(fileFullName);
if ((fileInfo.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
GetFolderStats(fileInfo);
else
GetFileStats(fileInfo);
}
catch (Exception ex)
{ msgLabel1.Text = ex.Message; msgLabel2.Text = null; }
} //ends private void DisplayFileFolderInfo(...
private void FileFolderLaunch(string columnName, int row)
{ //Launch a file, folder or disk volume
switch (columnName)
{
case GTFILENAME:
case GTDIRECTORY:
break;
case GTDISK:
case GTVOLUMEID:
{
string diskName = gridView[GTDISK, row].Value.ToString();
DisplayDriveInfo(diskName);
try
{
if (!PerformLaunch(diskName))
msgLabel1.Text = "Unable to launch " + diskName;
}
catch (Exception ex)
{ msgLabel1.Text = ex.Message; msgLabel2.Text = null; }
return;
}
default:
return;
}
string
fileName = "",
fileFullName = "";
if (!foldersOnlyDisplay)
fileName = gridView[GTFILENAME, row].Value.ToString().Trim();
if ((String.IsNullOrEmpty(fileName.Trim()))
|| (GTDIRECTORY == columnName))
{
fileFullName = Path.Combine(
gridView[GTDISK, row].Value.ToString(),
gridView[GTDIRECTORY, row].Value.ToString());
try
{
if (!Directory.Exists(fileFullName))
{
msgLabel1.Text = "Directory not found";
msgLabel2.Text = null;
return;
}
}
catch (Exception ex)
{
msgLabel1.Text = "Access to directory is denied";
msgLabel2.Text = ex.Message;
return;
}
}
else
{
fileFullName = Path.Combine(
Path.Combine(gridView[GTDISK, row].Value.ToString(),
gridView[GTDIRECTORY, row].Value.ToString()),
fileName);
try
{
if (!File.Exists(fileFullName))
{
msgLabel1.Text = "File not found";
msgLabel2.Text = null;
return;
}
}
catch (Exception ex)
{
msgLabel1.Text = "Access to file is denied";
msgLabel2.Text = ex.Message;
return;
}
}
try
{
FileInfo fileInfo = new FileInfo(fileFullName);
if ((fileInfo.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
GetFolderStats(fileInfo);
else
GetFileStats(fileInfo);
if(!PerformLaunch(fileInfo.FullName))
msgLabel1.Text = "Unable to launch " + fileInfo.FullName;
}
catch (Exception ex)
{ msgLabel1.Text = ex.Message; msgLabel2.Text = null; }
} //ends private void FileFolderLaunch(...
#region Menu processing
private void saveToolStripMenuItem_Click(object sender, EventArgs e)
{ //Menu->File->Save list
//creates either a .CSV file or a .TXT file depending on which view is active
using (SaveFileDialog savedlg = new SaveFileDialog())
{
savedlg.AddExtension = true;
if (MENUGRIDVIEW == gridListViewButton.Text)
{
savedlg.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*";
savedlg.Title = Application.ProductName + " save as text file";
}
else
{
savedlg.Filter = "Comma value seperated files (*.csv)|*.csv|All files (*.*)|*.*";
savedlg.Title = Application.ProductName + " save as tab separated file";
}
if (DialogResult.OK == savedlg.ShowDialog())
{
lock (syncobj)
{
string save_name = savedlg.FileName;
//if the menu shows 'Grid view', then the list view is visible
if (MENUGRIDVIEW == gridListViewButton.Text)
{ //save list view data as a text file
try
{
using (StreamWriter streamwriter = new StreamWriter(File.Create(save_name)))
{
foreach (string str in listBox1.Items)
streamwriter.WriteLine(str);
}
msgLabel2.Text = "Saved " + save_name;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, Application.ProductName,
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
else
{ //save grid view data as a tab seperated file
try
{
using (StreamWriter streamwriter = new StreamWriter(File.Create(save_name)))
{ //gather and write column titles
StringBuilder columnTitles = new StringBuilder(256);
foreach (DataColumn dc in table.Columns)
AddTitle(ref columnTitles, dc.ColumnName);
streamwriter.WriteLine(columnTitles.ToString());
//write all data rows
foreach (DataRow row in table.Rows)
{
columnTitles.Length = 0;
foreach (DataColumn dc in table.Columns)
{
if (String.IsNullOrEmpty(row[dc.ColumnName].ToString()))
{
if (GTFILENAME == dc.ColumnName)
AddTitle(ref columnTitles, "n/a");
else if (GTSIZE == dc.ColumnName)
AddTitle(ref columnTitles, "0");
}
else
AddTitle(ref columnTitles, row[dc.ColumnName].ToString());
}
streamwriter.WriteLine(columnTitles.ToString());
}
}
msgLabel2.Text = "Saved " + save_name;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, Application.ProductName,
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
} //ends lock (syncobj)
} //ends if (DialogResult.OK...
}
} //ends private void saveToolStripMenuItem_Click(...
private void AddTitle(ref StringBuilder sb, string str)
{ //creates a tab separated string of words for CSV files
if (str.IndexOf('\"') > -1) //handle embedded double quotes
{
StringBuilder newSB = new StringBuilder(256);
int index = str.IndexOf('\"');
newSB.Append(str.Substring(0, index++));
newSB.Append("\"\"");
while (index < str.Length)
{
if ("\"" == str.Substring(index, 1))
newSB.Append("\"\"");
else
newSB.Append(str.Substring(index, 1));
++index;
}
str = newSB.ToString();
}
char[] reservedChar = new char[] { ',', '\n', '~' }; //handle embedded commas and new line characters
if(str.IndexOfAny(reservedChar) > 0)
str = "\"" + str + "\"";
if (sb.Length > 1)
sb.Append("\t" + str);
else
sb.Append(str);
} //ends private void AddTitle(...
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{ // Menu->File->Exit
Application.Exit();
}
private void fontToolStripMenuItem_Click(object sender, EventArgs e)
{ // Menu->Options->Font
//select a different font
using (FontDialog fontDialog = new FontDialog())
{
if (fontDialog.ShowDialog() == DialogResult.OK)
{
ConfigInfo configInfo = new ConfigInfo();
configInfo.UseFont =
this.Font = fontDialog.Font;
}
}
}
private void showUnauthorizedFoldersToolStripMenuItem_Click(object sender, EventArgs e)
{ //Menu->Options->Show unauthorized folders
fileCountLabel.Text =
msgLabel1.Text = "";
ConfigInfo configInfo = new ConfigInfo();
showUnauthorizedFoldersToolStripMenuItem.Checked =
configInfo.ShowUnauthorizedFolders = !showUnauthorizedFoldersToolStripMenuItem.Checked;
if (configInfo.ShowUnauthorizedFolders)
msgLabel2.Text = "Showing unauthorized folder/file accesses";
else
msgLabel2.Text = "Not showing unauthorized folder/file accesses";
}
private void showReparsePointsToolStripMenuItem_Click(object sender, EventArgs e)
{ //Menu->Options->Show reparse points
fileCountLabel.Text =
msgLabel1.Text = "";
ConfigInfo configInfo = new ConfigInfo();
showReparsePointsToolStripMenuItem.Checked =
configInfo.ShowReparsePoints = !showReparsePointsToolStripMenuItem.Checked;
if (configInfo.ShowReparsePoints)
msgLabel2.Text = "Showing reparse points";
else
msgLabel2.Text = "Not showing reparse points";
}
private void showHiddenFoldersfilesToolStripMenuItem_Click(object sender, EventArgs e)
{ //Menu->Options->Show unauthorized folders
fileCountLabel.Text =
msgLabel1.Text = "";
ConfigInfo configInfo = new ConfigInfo();
showHiddenFoldersfilesToolStripMenuItem.Checked =
configInfo.ShowHiddenFoldersFiles = !showHiddenFoldersfilesToolStripMenuItem.Checked;
if (configInfo.ShowHiddenFoldersFiles)
msgLabel2.Text = "Showing hidden folders and files";
else
msgLabel2.Text = "Not showing hidden folders and files";
}
private void autoScrollingToolStripMenuItem_Click(object sender, EventArgs e)
{ //Menu->Options->Show unauthorized folders
fileCountLabel.Text =
msgLabel1.Text = "";
ConfigInfo configInfo = new ConfigInfo();
autoScrollMode =
autoScrollingToolStripMenuItem.Checked =
configInfo.AutoScrolling = !autoScrollingToolStripMenuItem.Checked;
if (configInfo.AutoScrolling)
msgLabel2.Text = "Auto scrolling on";
else
msgLabel2.Text = "Auto scrolling off";
}
private void helpToolStripMenuItem1_Click(object sender, EventArgs e)
{ // Menu->Help->Help
HelpForm helpForm = new HelpForm();
//put the new form to the right and down unless the caption would not be visible
System.Drawing.Rectangle formBounds = this.Bounds;
int x = formBounds.Width / 2 + formBounds.X;
int y = formBounds.Y + formBounds.Height / 10;
Screen scrn = Screen.FromControl(this);
if (x > scrn.WorkingArea.Right)
x = formBounds.Right - formBounds.Width / 4;
if (y > scrn.WorkingArea.Bottom)
y = formBounds.Bottom - formBounds.Height / 10;
System.Drawing.Point helpLocation = new System.Drawing.Point(x, y);
helpForm.FormLocation = helpLocation;
helpForm.FormHeight = formBounds.Height - formBounds.Height / 10;
helpForm.HelpFor = HelpForm.HelpForForm.MainForm;
helpForm.Show();
}
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{ // Menu->Help->About
//display the About form
using (AboutBox aboutDialog = new AboutBox())
{
aboutDialog.FormLocation = this.Location;
aboutDialog.ShowDialog();
}
}
private void ToolStripMenuItem_Click(object sender, EventArgs e)
{
if (sender is System.Windows.Forms.ToolStripMenuItem)
{
System.Windows.Forms.ToolStripMenuItem menuItem
= (System.Windows.Forms.ToolStripMenuItem)sender;
gridView.Columns[menuItem.Text].Visible =
menuItem.Checked = !menuItem.Checked;
usingView.UpdateVisible(menuItem.Text, menuItem.Checked);
}
} //ends private void ToolStripMenuItem_Click(...
private void removeSavedOptionsToolStripMenuItem_Click(object sender, EventArgs e)
{
ConfigInfo configInfo = new ConfigInfo(); //access configuration information
configInfo.RemoveIsolatedStorage();
fileCountLabel.Text =
msgLabel1.Text = "";
msgLabel2.Text = "Saved options file was deleted";
}
private void scanningViaEnumeratorToolStripMenuItem_Click(object sender, EventArgs e)
{
fileCountLabel.Text =
msgLabel1.Text = "";
ConfigInfo configInfo = new ConfigInfo();
scanningViaEnumeratorToolStripMenuItem.Checked =
configInfo.ScanningViaEnumerator = !scanningViaEnumeratorToolStripMenuItem.Checked;
if (configInfo.ScanningViaEnumerator)
msgLabel2.Text = "Scanning via enumerator technique";
else
msgLabel2.Text = "Scanning using FileInfo/DirInfo technique";
}
private void sequentialSearchToolStripMenuItem_Click(object sender, EventArgs e)
{
sequentialSearchToolStripMenuItem.Checked =
performSequentialSearch = !sequentialSearchToolStripMenuItem.Checked;
ConfigInfo configInfo = new ConfigInfo();
selectedDisks = configInfo.FilterSelectedDisks(selectedDisks);
HandleDriveSelection();
WaitForResolvedCompletion();
if (0 == resolvedDrives.Count)
msgLabel2.Text = "No disks were selected";
}
#endregion Menu processing
#region Grid cell clicked
private void CellContextClicked(object sender, DataGridViewCellContextMenuStripNeededEventArgs e)
{
List<string> columnTitles = new List<string>(table.Columns.Count); //array of string containing column names
foreach (DataColumn dc in table.Columns) //populate the array
columnTitles.Add(dc.ColumnName.ToString());
cellRowClicked = e.RowIndex;
cellColumnName = columnTitles[e.ColumnIndex].ToString();
}
/// <summary>
/// Grid was right clicked and content menu selected
/// </summary>
private void displayInfoStripMenuItem_Click(object sender, EventArgs e)
{
if (cellRowClicked != -1)
DisplayFileFolderInfo(cellColumnName, cellRowClicked);
cellRowClicked = -1;
}
private void launchFileToolStripMenuItem_Click(object sender, EventArgs e)
{
if (cellRowClicked != -1)
FileFolderLaunch(GTFILENAME, cellRowClicked);
cellRowClicked = -1;
}
private void launchFolderToolStripMenuItem_Click(object sender, EventArgs e)
{
if (cellRowClicked != -1)
FileFolderLaunch(GTDIRECTORY, cellRowClicked);
cellRowClicked = -1;
}
private void launchDiskToolStripMenuItem_Click(object sender, EventArgs e)
{
if (cellRowClicked != -1)
FileFolderLaunch(GTDISK, cellRowClicked);
cellRowClicked = -1;
}
private void KeyUpEvent(object sender, KeyEventArgs e)
{ //The Delete key was pressed
if (e.KeyCode == Keys.Delete)
{
if (MENULISTVIEW == gridListViewButton.Text)
{ //in grid view
UserRequestedDelete();
e.Handled = true;
}
else
e.Handled = false;
}
}
#endregion Grid cell clicked
}
}