Click here to Skip to main content
15,897,718 members
Articles / Programming Languages / C#

Multithreaded File/Folder Finder

Rate me:
Please Sign up or sign in to vote.
4.19/5 (18 votes)
26 May 2010CPOL17 min read 110.7K   5.6K   125  
File Find is fast, especially if you have multiple physical drives; version 2.1.0.17.
#if (!DEBUG)
#define useIsolatedStorage
#endif
//The XML configuration file may be written to isolated storage or to normal file storage.
//Normal file storage is useful for debugging as it is easy to view or modify the XML source.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.IO.IsolatedStorage;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Xml;

namespace FileFind
{
    /// <summary>
    ///   ConfigInfo holds configuration data as well as data that is commonly shared between 
    ///   program modules and forms.
    ///   Product/version information is maintained in AssemblyInfo.cs
    ///   Configuration information is stored when the application exits and retrieved at the next start up.
    ///   Saving of a filter list triggers an immediate save of the configuration information.
    ///   If useIsolatedStorage is #defined, application setting are saved in isolated storage specific to 
    ///  the program and user. Otherwise, the information is stored in the program execution directory
    ///  where it is simple to view or modify the XML source for testing.
    /// 
    ///   ConfigInfo is also used to pass data from various forms and dialogs back to the caller.
    /// </summary>
    [IsolatedStorageFilePermissionAttribute(SecurityAction.Demand, Unrestricted = true)]
    class ConfigInfo
    {
        #region Local constants and variables
        private object syncobj = new object();      //local lock object

        /// <summary>
        /// Product/version identification constants
        /// </summary>
        private const string PRODUCTDATE = "2010";
        //private static string PRODUCTVERSION = 
        //    System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
        // PRODUCTVERSION replaced with Application.Application.ProductVersion
        /// <summary>
        /// Maintenance
        /// Version 1.0.0.0 Initial coding
        ///         2.0.0.0 Code restructured and optimized based on hard won knowledge
        ///         2.1.0.0 Added ResolvePartitions logic to Form1.cs to eliminate
        ///             seek contention on partitioned physical drives.
        ///         2.1.0.3 Added reparse point processing (do not recurse into it)
        ///         2.1.0.4 Added time filters
        ///         2.1.0.5 Added hidden folder/file menu option
        ///         2.1.0.6 Switched from foreach (FileSystemInfo to FileSystemEnumerator in DiskScan
        ///             to significantly speed up access to network drives
        ///         2.1.0.7 Added Menu->Options->Scanning via enumerator to ease testing and
        ///             allow for Windows 7 bug. Windows 7 failed when using enumerator.
        ///         2.1.0.8 Added NumericScaling class
        ///         2.1.0.9 Final clean up before publication to www.codeproject.com
        ///         2.1.0.10 Changed .cvs to .csv file extention
        ///             Added code to correctly handle embedded commas, new line characters and double quotes for save to .CSV files
        ///             Modified exit from Excludes to refresh selected drive information
        ///             Modified .CSV save routine to properly handle reservered characters (comma and double quotes) and changed
        ///             the seperation character to a tab.
        ///         2.1.0.11 Modified menu titles and rearranged menu items. Changed opening instructions.
        ///             Added status area at bottom of form to report disks being searched and thread terminations.
        ///             Modified SelectAllDisks logic to handle a system with no drives.
        ///         2.1.0.12
        ///             Added "Waiting on logical/physical drive resolution" message to Form1.cs
        ///             Grid view of "Folders only" no longer has file name or size columns
        ///         2.1.0.13
        ///             Added busy cursor during logical/physical disk resolution, Sort and Grid view swap.
        ///             Totally revamped BeginUpdate/EndUpdate logic for filesFoundBox displays resulting in
        ///             better response and faster searches when a large number of hits are found.
        ///         2.1.0.14
        ///             Moved logical to physical disk resolution to LogicalPhysicalDiskResolution class
        ///             Corrected Form1.excludesButton_Click to resolve with currently selected disk drives.
        ///             Add disk info display to single/double click of Disk column in grid view.
        ///             Now launches Drive for double click.
        ///         2.1.0.15
        ///             Improved user identity checking in About.
        ///             Corrected an error in Directory delete.
        ///         2.1.0.16
        ///             Bypassed logical/physical disk resolution if only 1 disk is being searched.
        ///             Redrive SelectAllDisks after excludesButton_Click was selected
        ///             Disable Delete button if no entries in grid view
        ///             Used OnIdle event to enable the Start button only if a mask is present
        ///         2.1.0.17
        ///             Prepare for publication in CodeProject
        ///         2.1.0.18
        ///             Correct an object disposed when terminating the application in Form1.TerminateAllThreads by
        ///                 adding "catch (ObjectDisposedException)" to error handling in DiskScan routine. Also added
        ///                 "Application.DoEvents()" to Form1.TerminateAllThreads
        ///             Added a check for disk resolution completion before calling a modal form
        ///             Added Type.GetType("System.DateTime") to dates in the grid view
        ///             Added the ability to select which columns to display in the grid view
        ///             Changed the Disk column to a fixed width and added a Volume Id column
        ///             Allowed Parameters to be passed to the program's invocation
        ///         2.1.0.19
        ///             Changed updates to toolStripStatusLabel1 to call the UpdateStatus routine due to problems when
        ///                 UltraMon switched monitor screens during disk resolution.
        ///             Added code to start new forms with a location close to the original form as this looked much 
        ///                 better on multiple monitors.
        ///                 Grid view now honors a Delete key as well as the delete button.
        ///         3.0.0.0
        ///             Changed from IgnoreFolders to Exclude/Include rule processing
        ///             Save/restore grid view column visibility
        ///             Upgraded LogicalPhysicalDiskResolution class to support synchronous and asynchronous methods.
        ///             The upgrade required changing the Invoke to BeginInvoke in UpdateStatus
        ///             Corrected selection problems when using the track bars for date selection
        /// </summary>
        private const string CONFIGFILENAME = "FileFind.xml"; //name of the configuration file

        private static bool alreadyInitialized = false;     //determines if the following static fields are already loaded
        private static bool dirty = false;                  //determines if ConfigInfo should be saved at exit
        private static bool removedSavedOptions = false;    //Isolated storage is not to be written at termination

        //variables to be saved for the next execution of this program
        private static bool startWithGrid = false;      //start in List or Grid view
        private static Font usingFont = null;           //display panels using this font
        private static bool showUnauthorizedFolders;    //if True, security exceptions are displayed
        private static bool showReparsePoints;          //if True, reparse points are displayed
        private static bool showHiddenFoldersFiles;     //if True, search and show hidden folders and files
        private static bool scanningViaEnumerator;      //if True, search files and folders using enumerators
        private static bool autoScrolling;              //if true, auto scroll list view
        private static bool returnDriveLetters;         //used in SelectDiskPath
        private static Dictionary<string, GridInfoCollection> gridInfos = null;
        private static FilterListCollection filterLists = null; //filter lists from prior FileFind execution
        private static FilterList activeFilterList = null;      //currently active filter list

        #endregion Local constants and variables

        #region Properties

        public static string ProductDate
        { get { return PRODUCTDATE; } }

        /// <summary>
        /// Determines if the initial display should begin with a list or grid view
        /// List view is the inital default
        /// The current view is saved when the application exits and the
        /// application will be restarted with the same view.
        /// </summary>
        public bool StartWithGrid
        {   
            get { return startWithGrid; }
            set
            {
                if(value != startWithGrid)
                { startWithGrid = value; dirty = true; }
            }
        }

        /// <summary>
        /// Determines if a display of failed folder accesses should be created or not
        /// </summary>
        public bool ShowUnauthorizedFolders
        {   
            get { return showUnauthorizedFolders; }
            set { showUnauthorizedFolders = value; }
        }

        /// <summary>
        /// Determines if a display of reparse points should be created or not
        /// </summary>
        public bool ShowReparsePoints
        {
            get { return showReparsePoints; }
            set { showReparsePoints = value; }
        }
        /// <summary>
        /// Determines if hidden folders or files should be shown and searched
        /// </summary>
        public bool ShowHiddenFoldersFiles
        {   
            get { return showHiddenFoldersFiles; }
            set { showHiddenFoldersFiles = value; dirty = true; }
        }

        /// <summary>
        /// Determines if DiskScan should use enumerator scanning or FileSystemInfo calls
        /// </summary>
        public bool ScanningViaEnumerator
        {
            get { return scanningViaEnumerator; }
            set { scanningViaEnumerator = value; dirty = true; }
        }

        /// <summary>
        /// Turns list view automatic scrolling on or off
        /// Retrieves the current setting
        /// </summary>
        public bool AutoScrolling
        {
            get { return autoScrolling; }
            set { autoScrolling = value; dirty = true; }
        }

        /// <summary>
        /// Returns true if drive letters are to be returned from the Disk/Path selection form
        /// Returns false if volume labels are being returned
        /// </summary>
        public bool ReturnDriveLetters
        {
            get { return returnDriveLetters; }
            set { returnDriveLetters = value; dirty = true; }
        }

        /* obsolete starting in release 3.0.0.0
        public ArrayList IgnoreFolders
        {   //a set of folder nodes, drives or specific drive folder combinations to be excluded
            //populated by the IgnoreFolders class
            get { lock (syncobj) { return ignoreFolders; } }
            set { lock (syncobj) { ignoreFolders = value; dirty = true; } }
        }
         * */

        /// <summary>
        /// font to use for forms and displays
        /// selected via menu option
        /// </summary>
        public Font UseFont
        {   
            get { lock (syncobj) { return usingFont; } }
            set { lock (syncobj) { usingFont = value; dirty = true; } }
        }

        /// <summary>
        /// Returns a reasonable list of folders that typically do not contain user files
        /// and rarely need searching.
        /// </summary>
        public ArrayList DefaultFolders
        {   //generate a default exclusion list
            get
            {
                ArrayList defaultFolders = new ArrayList();
                defaultFolders.Add("System Volume Information");
                defaultFolders.Add("$Recycle.Bin");
                defaultFolders.Add("RECYCLER");             //NTFS
                defaultFolders.Add("RECYCLED");             //FAT
                defaultFolders.Add("Program Files");        //found on 32 and 64 bit systems
                defaultFolders.Add("Program Files (x86)");  //found on 64 bit systems
                //Windows 7
                defaultFolders.Add("WindowsImageBackup");
                defaultFolders.Add("PerfLogs");
                return defaultFolders;
            }
        }
        #endregion Properties

        #region GridColumnsInformation
        /// <summary>
        /// Returns a clone of the requested grid view information
        /// or null if the grid view does not exist
        /// </summary>
        public GridInfoCollection GetGridView(string viewName)
        {
            GridInfoCollection gridInfo = null;
            if (gridInfos.TryGetValue(viewName, out gridInfo))
                return (GridInfoCollection)gridInfo.Clone();
            return null;
        }

        /// <summary>
        /// Adds or replaces a named grid view to the ConfigInfo
        /// </summary>
        /// <param name="gridInfo"></param>
        public void StoreGridView(GridInfoCollection gridInfo)
        {
            dirty = true;
            gridInfo.SortByDisplayOrder();                  //sort is not required, it just makes it easier to read
            if (gridInfos.ContainsKey(gridInfo.ViewName))
                gridInfos[gridInfo.ViewName] = gridInfo;    //The key was found; change its value.
            else
                gridInfos.Add(gridInfo.ViewName, gridInfo); //Grid view does not exit, add it.
        }

        /// <summary>
        /// Remove a grid view
        /// </summary>
        /// <param name="viewName"></param>
        public void RemoveGridView(string viewName)
        { gridInfos.Remove(viewName); dirty = true; }
        public void RemoveGridView(GridInfoCollection gridInfo)
        { gridInfos.Remove(gridInfo.ViewName); dirty = true; }

        /// <summary>
        /// Remove all grid views
        /// </summary>
        public void ClearGridViews()
        { gridInfos.Clear(); }

        #endregion GridColumnsInformation

        #region Filter lists
        /// <summary>
        /// Returns or Sets the complete collection or filter lists
        /// </summary>
        public FilterListCollection MasterFilterListCollection
        {
            get { return filterLists; }
            set { filterLists = value; }
        }

        /// <summary>
        /// Returns or sets the active filter list
        /// </summary>
        public FilterList ActiveFilterList
        {
            get { return activeFilterList; }
            set
            {
                activeFilterList = value;
                if (null != activeFilterList)
                {
                    try { filterLists.SetInUse(activeFilterList); }
                    catch { }
                    dirty = true;
                }
            }
        }

        /// <summary>
        /// Returns the filter rules currently being used
        /// </summary>
        public static FilterRules GetFilterRules
        {
            get
            {
                if (null == activeFilterList)       //if no filter rules exist, build an include all rule
                    return FilterRules.IncludeAllFilterRule;
                //convert the active filter list into filter rules
                FilterList activeClone = FilterList.ValidateFilterList(activeFilterList);
                FilterRules filterRules = new FilterRules();
                filterRules.PrepareRules(activeClone, true);
                return filterRules;
            }
        }
        #endregion Filter lists

        #region Public functions
        /// <summary>
        /// Class constructor
        /// On first use, initializes all the static fields to default values then loads
        /// stored values from a prior execution.
        /// </summary>
        public ConfigInfo()
        {
            if (!alreadyInitialized)
            {   //initialize all configuration data when first called
                //perform the initializations outside the try statement as the try may fail
                lock (syncobj)
                {   //set default values
                    string myTrue = true.ToString();
                    alreadyInitialized = true;
                    filterLists = new FilterListCollection();
                    gridInfos = new Dictionary<string, GridInfoCollection>();
                    scanningViaEnumerator =
                    showHiddenFoldersFiles =
                    showUnauthorizedFolders =
                    showReparsePoints =
                    startWithGrid = false;
                    returnDriveLetters =
                    autoScrolling = true;
                    string mutexName = GetMutexName();
                    Mutex mutex = new Mutex(false, mutexName);
                    try
                    {
                        mutex.WaitOne();    //gain exclusive control
                        //read settings from the XML file saved after prior execution of this program
#if useIsolatedStorage
                        using (Stream isolatedStorageStream = new IsolatedStorageFileStream(CONFIGFILENAME,
                            FileMode.Open, IsolatedStorageFile.GetUserStoreForAssembly()))
#else
                        using (Stream isolatedStorageStream = new FileStream(CONFIGFILENAME, FileMode.Open))
#endif
                        {
                            XmlDocument xmldoc = new XmlDocument();
                            using (StreamReader ifs = new StreamReader(isolatedStorageStream))
                            { xmldoc.Load(ifs); }

                            XmlNode listOrGrid = xmldoc.SelectSingleNode("FileFind/StartView");
                            if ((null != listOrGrid) && ("Grid" == listOrGrid.InnerText))
                                startWithGrid = true;

                            XmlNode showHidden = xmldoc.SelectSingleNode("FileFind/Hidden");
                            if ((null != showHidden) && (myTrue == showHidden.InnerText))
                                showHiddenFoldersFiles = true;

                            XmlNode scanning = xmldoc.SelectSingleNode("FileFind/ScanningViaEnumerator");
                            if ((null != scanning) && (myTrue == scanning.InnerText))
                                scanningViaEnumerator = true;
                            else
                                scanningViaEnumerator = false;

                            XmlNode autoScroll = xmldoc.SelectSingleNode("FileFind/AutoScroll");
                            if ((null != autoScroll) && (myTrue == autoScroll.InnerText))
                                autoScrolling = true;
                            else
                                autoScrolling = false;

                            XmlNode driveLetters = xmldoc.SelectSingleNode("FileFind/DriveLetters");
                            if ((null != driveLetters) && (myTrue == driveLetters.InnerText))
                                returnDriveLetters = true;
                            else
                                returnDriveLetters = false;

                            XmlNode filters = xmldoc.SelectSingleNode("FileFind/FilterListCollection");
                            if (null != filters)
                            {
                                try
                                {   //load the Xml to the filterLists collection
                                    foreach (XmlNode xNode in filters)
                                    {
                                        FilterList filterList = new FilterList();
                                        filterList.Name = xNode.NamespaceURI;
                                        filterList.AllowDuplicates = (xNode.Attributes["AllowDuplicates"].Value.ToString() == myTrue);
                                        filterList.CurrentlyInUse = (xNode.Attributes["CurrentlyInUse"].Value.ToString() == myTrue);
                                        foreach (XmlNode yNode in xNode)
                                            filterList.Add(new Filter(yNode.Attributes["Function"].Value.ToString(),
                                                    yNode.Attributes["Type"].Value.ToString(),
                                                    yNode.NamespaceURI));
                                        filterLists.Add(filterList);
                                    }
                                    filterLists.IsDirty = false;    //initial collection load completed
                                }
                                catch (Exception ex)
                                {
                                    MessageBox.Show(ex.InnerException.ToString(),
                                        Application.ProductName + " FilterListCollection",
                                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                                }
                                activeFilterList = filterLists.GetInUse;
                            }
                            else
                            {
                                XmlNode ignore = xmldoc.SelectSingleNode("FileFind/IgnoreFolders");
                                ArrayList ignoreFolders = new ArrayList();  //contains file and folder names to exclude when searching
                                //used to maintain backward compatibility for FileFind XML saved option files prior to release 3.0.0.0
                                if (null != ignore)
                                    foreach (XmlNode xNode in ignore)
                                        ignoreFolders.Add(xNode.InnerText);
                                else
                                    ignoreFolders = DefaultFolders;
                                //convert ignorefolders to a FilterList
                                FilterList ignoreList = new FilterList();
                                ignoreList.Name = "Prior Excludes";
                                foreach (string exclude in ignoreFolders)
                                {
                                    string str = exclude.Replace('/', '\\');
                                    if ((str.Length > 3)
                                    && ((':' == str[1]) && ('\\' == str[2]) && (Char.IsLetter(str[0]))))
                                        ignoreList.Add(new Filter(FilterList.FilterExclude, FilterList.FilterPath, str));
                                    else if ((3 == str.Length)
                                    && ((':' == str[1]) && ('\\' == str[2]) && (Char.IsLetter(str[0]))))
                                        ignoreList.Add(new Filter(FilterList.FilterExclude, FilterList.FilterDrive, str));
                                    else
                                        ignoreList.Add(new Filter(FilterList.FilterExclude, FilterList.FilterFolder, str));
                                }
                                filterLists.Add(ignoreList);
                                ActiveFilterList = ignoreList;
                            }

                            XmlNode gridViews = xmldoc.SelectSingleNode("FileFind/GridViews");
                            if (null != filters)
                            {
                                try
                                {   //load the Xml to the GridInfoCollection collection
                                    foreach (XmlNode xNode in gridViews)
                                    {
                                        GridInfoCollection gridInfo = new GridInfoCollection();
                                        gridInfo.ViewName = xNode.NamespaceURI;
                                        foreach (XmlNode yNode in xNode)
                                        {
                                            string colName = yNode.Attributes["ColName"].Value.ToString();
                                            bool menuVisible = (myTrue == yNode.Attributes["Visible"].Value.ToString());
                                            string displayOrder = yNode.Attributes["DisplayOrder"].Value.ToString(CultureInfo.InvariantCulture);
                                            int menuDisplayOrder = System.Convert.ToInt32(displayOrder, CultureInfo.InvariantCulture);
                                            string width = yNode.Attributes["Width"].Value.ToString(CultureInfo.InvariantCulture);
                                            int menuWidth = System.Convert.ToInt32(width, CultureInfo.InvariantCulture);
                                            gridInfo.Add(new ColumnInfo(colName, menuVisible, menuDisplayOrder, menuWidth));
                                        }
                                        gridInfos.Add(gridInfo.ViewName, gridInfo);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    MessageBox.Show(ex.InnerException.ToString(),
                                        Application.ProductName + " FilterListCollection",
                                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                                }
                            }
                            try
                            {
                                XmlNode useFont = xmldoc.SelectSingleNode("FileFind/UseFont");
                                if (null != usingFont)
                                {
                                    XmlNode root;
                                    root = xmldoc.SelectSingleNode("FileFind/UseFont/Name");
                                    string fontName = root.InnerText;
                                    root = xmldoc.SelectSingleNode("FileFind/UseFont/Size");
                                    string swFont = root.InnerText;
                                    float currentSize = System.Convert.ToSingle(swFont, CultureInfo.InvariantCulture);
                                    FontStyle swStyle = new FontStyle();
                                    root = xmldoc.SelectSingleNode("FileFind/UseFont/Bold");
                                    if (myTrue == root.InnerText)
                                        swStyle |= FontStyle.Bold;
                                    root = xmldoc.SelectSingleNode("FileFind/UseFont/Italic");
                                    if (myTrue == root.InnerText)
                                        swStyle |= FontStyle.Italic;
                                    root = xmldoc.SelectSingleNode("FileFind/UseFont/Strikeout");
                                    if (myTrue == root.InnerText)
                                        swStyle |= FontStyle.Strikeout;
                                    root = xmldoc.SelectSingleNode("FileFind/UseFont/Underline");
                                    if (myTrue == root.InnerText)
                                        swStyle |= FontStyle.Underline;
                                    usingFont = new Font(fontName, currentSize, swStyle);
                                }
                            }
                            catch (Exception xe)
                            {
                                MessageBox.Show(xe.InnerException.ToString(),
                                    Application.ProductName + " UseFont",
                                    MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                            }
                        }
                    } //ends read settings from the XML file saved 
                    catch (SecurityException se)
                    {
                        MessageBox.Show(se.Message,
                            Application.ProductName + " Config loading",
                            MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                    }
                    catch { }
                    finally { mutex.ReleaseMutex(); }
                    ActiveFilterList = filterLists.GetInUse;
                } //ends lock (syncobj)
            } //ends if (!alreadyInitialized)
        } //ends public ConfigInfo()

        /// <summary>
        /// Saves configuration values for the next execution of the application
        /// </summary>
        public void SaveConfig()
        {   //XML Create (creates an XML file via native calls)
            if((dirty) && (!removedSavedOptions))
            lock (syncobj)
            {
                string mutexName = GetMutexName();
                Mutex mutex = new Mutex(false, mutexName);
                try
                {
                    mutex.WaitOne();    //gain exclusive control
#if useIsolatedStorage
                    using (Stream isolatedStorageStream =
                        new IsolatedStorageFileStream(CONFIGFILENAME, FileMode.Create, IsolatedStorageFile.GetUserStoreForAssembly()))
#else
                    using (Stream isolatedStorageStream = new FileStream(CONFIGFILENAME, FileMode.Create))
#endif
                    using(XmlTextWriter appconfig = new XmlTextWriter(isolatedStorageStream, Encoding.UTF8))
                    {
                        appconfig.Formatting = Formatting.Indented;
                        appconfig.WriteStartDocument();
                        DateTime newDate = DateTime.Now;
                        appconfig.WriteComment("Created " + newDate.ToString(CultureInfo.InvariantCulture));
                        appconfig.WriteStartElement("FileFind");
                        appconfig.WriteCData(@"<>\&");

                        if (startWithGrid)
                            appconfig.WriteElementString("StartView", "Grid");
                        else
                            appconfig.WriteElementString("StartView", "List");

                        appconfig.WriteElementString("Hidden", showHiddenFoldersFiles.ToString());
                        appconfig.WriteElementString("ScanningViaEnumerator", scanningViaEnumerator.ToString());
                        appconfig.WriteElementString("AutoScroll", autoScrolling.ToString());
                        appconfig.WriteElementString("DriveLetters", returnDriveLetters.ToString());

                        if (filterLists != null && filterLists.Count > 0)
                            filterLists.Export(appconfig);  //store all filter lists

                        if (0 != gridInfos.Count)
                        {
                        appconfig.WriteStartElement("GridViews");
                        foreach (KeyValuePair<string, GridInfoCollection> kvp in gridInfos)
                            {   //record each FilterList
                                GridInfoCollection gridInfo = kvp.Value;
                                appconfig.WriteStartElement("GridView", gridInfo.ViewName);
                                foreach (ColumnInfo columnInfo in gridInfo)
                                {
                                    appconfig.WriteStartElement("GridColumn");
                                    appconfig.WriteAttributeString("ColName", columnInfo.ColumnName);
                                    appconfig.WriteAttributeString("Visible", columnInfo.Visible.ToString());
                                    appconfig.WriteAttributeString("DisplayOrder", columnInfo.DisplayOrder.ToString(CultureInfo.InvariantCulture));
                                    appconfig.WriteAttributeString("Width", columnInfo.Width.ToString(CultureInfo.InvariantCulture));
                                    appconfig.WriteEndElement();    //ends ColumnInfo
                                }
                                appconfig.WriteEndElement();    //ends GridView
                            }
                            appconfig.WriteEndElement();    //ends gridInfos
                        }

                        if (null != usingFont)
                        {
                            appconfig.WriteStartElement("UseFont");
                            appconfig.WriteElementString("Name", usingFont.Name.ToString());
                            appconfig.WriteElementString("Style", usingFont.Style.ToString());
                            appconfig.WriteElementString("Size", usingFont.Size.ToString(CultureInfo.InvariantCulture));
                            appconfig.WriteElementString("Bold", usingFont.Bold.ToString());
                            appconfig.WriteElementString("Italic", usingFont.Italic.ToString());
                            appconfig.WriteElementString("Strikeout", usingFont.Strikeout.ToString());
                            appconfig.WriteElementString("Underline", usingFont.Underline.ToString());
                            appconfig.WriteEndElement();    //ends UseFont
                        }
                        appconfig.WriteEndDocument();
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message + "\n" + ex.InnerException, 
                        Application.ProductName,
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
                finally { mutex.ReleaseMutex(); }   
            } //ends lock (syncobj)
        } //ends public void SaveConfig()

        /// <summary>
        /// Show all ready disks as selected except explicitly excluded disks (via Disk selection form).
        /// Returns an ArrayList of selected disks and a count of selected disks.
        /// If the count is -1 then all ready disks have been selected.
        /// </summary>
        /// <param name="diskCount">returns number of drives selected</param>
        /// <returns>names of selected drives</returns>
        public ArrayList SelectAllDisks(out int diskCount)
        {
            ArrayList selected = new ArrayList();
            diskCount = 0;
            DriveInfo[] allDrives = null;
            try { allDrives = DriveInfo.GetDrives(); }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message,
                    Application.ProductName + " ConfigInfo.SelectAllDisks",
                    MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                allDrives = null;
            }
            FilterRules localFilterRules = GetFilterRules;
            if (allDrives != null)
            {
                int readyDrives = 0;
                foreach (DriveInfo drive in allDrives)
                {   //show only available drives
                    if (drive.IsReady)
                    {
                        ++readyDrives;
                        if (localFilterRules.SearchAnyPath(drive.Name))
                            selected.Add(drive.Name);
                    }
                }
                diskCount = selected.Count;
                if (diskCount == readyDrives)
                    diskCount = -1; //all drives selected
            }
            return selected;
        } //ends public ArrayList SelectAllDisks(...

        public ArrayList FilterSelectedDisks(ArrayList currentlySelected)
        {   //show all disks as selected except explicitly excluded disks
            //returns an ArrayList of selected disks and a count of selected disks
            //if the count is -1 then all disks have been selected
            FilterRules localFilterRules = GetFilterRules;
            ArrayList selected = new ArrayList();
            foreach (string selectedDrive in currentlySelected)
            {//show drives available
                DriveInfo drive = new DriveInfo(selectedDrive);
                if ((drive.IsReady)
                && (localFilterRules.SearchThisPath(new DirectoryInfo(drive.Name))))
                    selected.Add(drive.Name);
            }
            return selected;
        } //ends public ArrayList FilterSelectedDisks(...


        public void RemoveIsolatedStorage()
        {
            removedSavedOptions = true;
            try
            {
#if useIsolatedStorage
                IsolatedStorageFile isoFile = IsolatedStorageFile.GetStore(IsolatedStorageScope.User |
                    IsolatedStorageScope.Assembly,
                    typeof(System.Security.Policy.Url),
                    typeof(System.Security.Policy.Url));

                String[] fileNames = isoFile.GetFileNames(CONFIGFILENAME);

                foreach (string fileName in fileNames)
                {
                    // Delete the files.
                    isoFile.DeleteFile(fileName);
                }
#else
                    File.Delete(CONFIGFILENAME);
#endif
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message,
                    Application.ProductName + " Isolated storage / file delete",
                    MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        } //ends public RemoveIsolatedStorage()
        #endregion Public functions

        #region Private functions
        private string GetMutexName()
        { return Path.GetPathRoot(Environment.CurrentDirectory).Replace("\\", "_").Replace("/", "_") + "FileFindMutex"; }
        #endregion Private functions
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
Software Developer (Senior) retired
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions