Monday, February 20, 2012

Using Visual C# 2010 Express to Check Multiple Folders for Duplicate Files Update


Using Visual C# 2010 Express to Check Multiple Folders for Duplicate Files Update

Since my previous post I have discovered an error such that not all the files of folders get compared.  So an update of the Form1.cs code is provided below.

Also, I have noticed a problem with my attempt to provide the user with a running status of the progress of the compares.  When I ran the application with the debugger the label control that displayed text as to the number of folders checked and the number of files checked and the label control that displayed the number of duplicates continuously updated as intended.  However, when the application was run via its .exe executable the labels would initially be updated.  But very shortly the wait cursor would be displayed without being requested and the updating would cease until all the compares had occurred when the cursor would return to the default and the totals would be displayed.

I have been unable to find a way to avoid this.  I've done internet searches and found various posts that purport to show how the programmer can prevent this from happening – that is, have updates of controls actually happen and be displayed.  None of those that I found have worked with my application.

I've also tried a progress bar which should surely work.  Again, it is continually updated if I run the application via the Visual C# 2010 Express debugger.  But, if the application is run via its executable, the wait cursor appears and the labels and progress bar cease being updated after the first 20 files or so.  So the progress bar no longer shows progress.

In addition I created a second project in which I used a worker thread to do the compares while the Form1 thread slept for 500 ms at a time and then did the updates in the Form1 thread before sleeping again.  No change in the update behavior.  That is, the label text didn't change and the progress bar didn't show any progress.

Any ideas anyone?

Form1.cs code

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace Compare
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            // (Mostly) generated control initialization.
            InitializeComponent();

            // Add selections to the combo boxes.
            extensionComboBox.MaxDropDownItems = 4;
            extensionComboBox.Items.Add(extensions[0]);
            extensionComboBox.Items.Add(extensions[1]);
            extensionComboBox.Items.Add(extensions[2]);
            extensionComboBox.Items.Add(extensions[3]);

            existingReport.MaxDropDownItems = 2;
            existingReport.Items.Add(reportOptions[0]);
            existingReport.Items.Add(reportOptions[1]);

            // Create string from byte arrays to get new lines in the duplicates file.
            Byte[] cR = new Byte[] { 13 };
            Byte[] lF = new Byte[] { 10 };
            crNL = Encoding.ASCII.GetString(cR) + Encoding.ASCII.GetString(lF);
        }

        //----------------------------------------------------------------------
        // Compare files in the selected folders.
        private void CompareFiles()
        {
            // Display progress bar.
            progressBar.Minimum = 1;
            progressBar.Maximum = 0;
            for (int f = 0; f < folderCount; f++)
            {
                progressBar.Maximum = progressBar.Maximum + 
                                      folderFile[f].list.Count();
            }
            progressBar.Value = 1;
            progressBar.Step = 1;
            progressBar.Visible = true;
            progressBar.Update();

            // Display Please Wait.
            pleaseWait.Visible = true;
            pleaseWait.Refresh();

            // Compare files of all folders starting with first file of first folder
            // to compare with the other files of that folder and then those of the
            // other folders.  Then proceed to the next file of the first folder and
            // repeat.  Then to the first file of the next folder to check the files
            // of that folder and the remaining folders.  And repeat.
            for (int f = 0; f < folderCount; f++) // Check folders for those not yet
            {                                                       //  completely compared
                // Select initial default folder and list.
                int defaultFolder = f;
                IEnumerable<System.IO.FileInfo> defaultList =
                                                folderFile[defaultFolder].list;

                FileInfo lastIndex = defaultList.Last();
                // Ignore list if no files with selected extension.
                if (defaultList.Count() > 0)
                {
                    string defaultFileName = defaultList.First().FullName;
                    FileStream defaultFileStream = null;

                    defaultIndex = 0;
                    defaultCount = 0;
                    if (defaultFiles == null)
                    {
                        defaultFiles = new string[defaultList.Count()];
                    }
                    else if (defaultFiles.Count() < defaultList.Count())
                    {
                        defaultFiles = new string[defaultList.Count()];
                    } // else reuse the defaultFiles array
                    foreach (var v in defaultList)
                    {
                        defaultFiles[defaultCount] = v.FullName;
                        defaultCount++;
                    }

                    // Compare particular file in the list to the other files of the list
                    // and the other lists (if not already in the duplicate table).
                    for (defaultIndex = 0; defaultIndex < defaultCount; defaultIndex++)
                    {
                       // Select the file.
                       defaultFileName = defaultFiles[defaultIndex];
                        // Ignore file if already found as a duplicate.
                        if (!InDuplicateTable(defaultFileName))
                        { 
                            // Open the selected file for Read-Only.
                            try
                            {
                                defaultFileStream = new FileStream(defaultFileName,
                                                                   FileMode.Open,
                                                                   FileAccess.Read);
                                if (defaultFileStream != null)
                                {   // Find any duplicates of the selected file.
                                    CompareSelectedFile(defaultFolder, defaultFileName,
                                                        defaultFileStream );
                                    // Close the selected file.
                                    defaultFileStream.Close();

                                    // Attempt to continue update without showing the
                                    // wait cursor when running exe.
                                    comparedCount++;
                                    CompareStatus.Text = "Folder " + (f + 1) + "  " +
                                                         comparedCount + " files compared";
                                    CompareStatus.Visible = true;
                                    CompareStatus.Refresh();
                                    numberDuplicates.Text = "Number of duplicate files is "
                                                            + duplicatesReported;
                                    numberDuplicates.Visible = true;
                                    numberDuplicates.Refresh();
                                    progressBar.Value = comparedCount;
                                    progressBar.PerformStep();
                                    progressBar.Update();
                                } // end if
                            } // end try
                            catch (Exception ex)
                            {
                                MessageBox.Show("Error: Unable to open first file " +
                                                defaultFileName +
                                                " " + ex.Message);
                            }
                        } // end if (!InDuplicateTable(defaultFileName))
                      
                    } // end loop for each file in current list

                } // end if (defaultList.Count() > 0)

                // Indicate that the folder has been searched.
                folderFile[f].searched = true;

            } // end loop thru selected folders

            // Hide Please Wait and progress bar.
            pleaseWait.Visible = false;
            progressBar.Visible = false;

            // Output count of duplicate files.
            Byte[] text = new UTF8Encoding(true).GetBytes("Number of duplicate files is "
                + duplicatesReported + crNL);
            duplicatesReport.Write(text, 0, text.Length);
            duplicatesReport.Flush();

            // Display Done OK button to allow user to see number of duplicate files.
            // When clicked, the application will be terminated.
            doneButton.Visible = true;

        } // end method CompareFiles

        //----------------------------------------------------------------------
        // Compare particular file in the list to the other files of the
        // selected folder list and the other lists that follow it.
        // Notes: All files in a list previous to the selected folder have
        //        already been compared.
        private void CompareSelectedFile(int selectedFolder, string selectedFileName,
                                         FileStream fs1)
        {
            for (int f = selectedFolder; f < folderCount; f++)
            {   // Check folders for those not yet completely compared
                if (f == selectedFolder)
                {   // Compare from next file forward thru the selected folder
                    for (int index = defaultIndex+1; index < defaultCount; index++)
                    {
                        FileCompare(fs1, defaultFiles[index]);
                    }
                }
                else
                {   // Compare all the files of the folder
                    foreach (var v in folderFile[f].list)
                    {
                       FileCompare(fs1, v.FullName);
                    }
                }
            }  // end loop over folders

         } // end method CompareSelectedFile

        //----------------------------------------------------------------------
        // This method accepts two strings the represent two files to
        // compare. A return value of 0 indicates that the contents of the files
        // are the same. A return value of any other value indicates that the
        // files are not the same.
        // Notes: This method is somewhat modified from a Microsoft example.
        private void FileCompare(FileStream fs1, string file2)
        {
            int file1byte;
            int file2byte;

            FileStream fs2 = null;

            // Open the second file.
            try
            {
                fs2 = new FileStream(file2, FileMode.Open, FileAccess.Read);
            }
            catch (Exception ex)
            {
                if (ex.Message.StartsWith("Access to the path") &&
                     fileError.StartsWith("Access to the path"))
                { // bypass the reporting of the exception
                }
                else
                { // display the first instance of the exception
                    fileError = ex.Message;
                    MessageBox.Show("Error: Unable to open second file " + file2 + " "
                        + ex.Message + " Further such errors will be ignored.");
                }
            }

            // If can't open the file, return since can't compare the files.
            if (fs2 == null)
            {
                MessageBox.Show("ERROR: Couldn't open " + file2);
                return;
            }

            // Check the file sizes. If they are not the same, the files
            // are not the same.
            if (fs1.Length != fs2.Length)
            {
                // Close the file and return since no need to compare the files
                fs2.Close();
                return;
            }

            // Read and compare a byte from each file until either a
            // non-matching set of bytes is found or until all the bytes
            // have been compared.
            int bytesRead = 0;
            do
            {
                // Read one byte from each file.
                file1byte = fs1.ReadByte();
                file2byte = fs2.ReadByte();
                bytesRead++;
            }
            while ((file1byte == file2byte) && (bytesRead <= fs1.Length)) ;

            // Close the file.
            fs2.Close();

            // If the last bytes read are equal, the files are the same.  Add the
            // duplicate file pair to the duplicate array and duplicates report.
            if ((file1byte - file2byte) == 0 )
            {   // add file pair to duplicate array
                if (duplicateCount < maxDuplicates)
                {
                    duplicateFiles[duplicateCount] =
                        new DuplicateFile(fs1.Name, file2);
                    duplicateCount++;
                }
                else if (!maxDuplicatesDisplayed)
                {
                    maxDuplicatesDisplayed = true;
                    MessageBox.Show("ERROR: Maximum number of duplicates of "
                                     + maxDuplicates + " exceeded");
                }

                // Add file pair to duplicates report
                duplicatesReported++;
                Byte[] text = new UTF8Encoding(true).GetBytes(fs1.Name
                                   + " " + file2 + crNL);
                duplicatesReport.Write(text, 0, text.Length);
                duplicatesReport.Flush();
            } // end if

        } // end function FileCompare

        //----------------------------------------------------------------------
        // Return true if file is in the duplicate table. 
        // Note: The name1 column is for the default file for which duplicates
        //       have been found.  The file passed is for a newly chosen file
        //       so could only be a file in the name2 column.
        private bool InDuplicateTable(string file)
        {
            for (int i = 0; i < duplicateCount; i++)
            {
                if (file.Equals(duplicateFiles[i].name2))
                {
                    return true;
                }
            }

            return false;

        } // end function InDuplicateTable

        //----------------------------------------------------------------------
        // Obtain folder names and display in list box and open report file.
        private void ObtainFolderNames(string ext) // ext is selected file extension
        {
            string folder = "";
            bool selectFolder = true;
            System.IO.DirectoryInfo[] dir = new DirectoryInfo[maxFolders];

            // Do not allow the user to create new files via the FolderBrowserDialog.
            folderBrowserDialog1.ShowNewFolderButton = false;

            // Obtain folders to be searched for duplicate files with the
            // selected extension.
            while (selectFolder && folderCount < dir.Length)
            {
                if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
                {
                    folder = folderBrowserDialog1.SelectedPath;

                    // Check that folder not already selected.
                    bool newFolder = true;
                    for (int f = 0; f < folderCount; f++)
                    {
                        if (folder.Equals(folderFile[f].name))
                        {
                            newFolder = false;
                            break;
                        }
                    }

                    if (newFolder)
                    {
                        folderListBox.Items.Add(folder);
                        folderListBox.Refresh();
                        dir[folderCount] = new System.IO.DirectoryInfo(folder);

                        IEnumerable<System.IO.FileInfo> folderList =
                            dir[folderCount].GetFiles(
                               ext, System.IO.SearchOption.AllDirectories);
                        folderFile[folderCount] = new FolderFile(folder, folderList);
                        folderCount++;
                    } // end if (newFolder)
                }
                else
                {
                    selectFolder = false;
                }
            } // end select folders loop
            folderListBox.Refresh();

            // Quit if nothing selected.
            if (folderCount == 0)
            {
                Console.WriteLine("ERROR: no folders selected");
                this.Close(); // close form
                return;
            }

            // Open disk file to report duplicates.  Check if already available
            // and, if so, ask if to overwrite or add new entries at the end. 
            // If not available, create the file.
            duplicatesReportFileName = folderFile[0].name + "\\DuplicateFiles.txt";
            try
            {
                duplicatesReport = File.Open(duplicatesReportFileName,
                                             FileMode.Open, FileAccess.Read);
                long size = duplicatesReport.Length;
                if (size > 0)
                {
                    duplicatesReport.Close();
                    existingReport.Visible = true;
                    existingReport.Refresh();
                    return; // allow append or overwrite to be selected
                }
                else
                {
                    duplicatesReport.Close();
                    duplicatesReport = File.Open(duplicatesReportFileName,
                                                 FileMode.Append, FileAccess.Write);
                }
            }
            catch //(Exception ex)
            {
                duplicatesReport = File.Open(duplicatesReportFileName,
                                             FileMode.CreateNew, FileAccess.Write);
            }

            // Compare the selected files.
            CompareFiles();

        } // end method ObtainFolderNames

        //----------------------------------------------------------------------
        // Event handlers

        // Hide OK button and then select the folders of the files to be
        // compared and do the compare.
        private void buttonOK_Click(object sender, EventArgs e)
        {
            buttonOK.Visible = false;
            ObtainFolderNames(extension);

        } // end event handler buttonOK_Click

        //----------------------------------------------------------------------
        // Allow operator to terminate
        private void doneButton_Click(object sender, EventArgs e)
        {
            doneButton.Visible = false;
            this.Close(); // close form
            return; // finished running
        } // end event handler doneButton_Click

        //----------------------------------------------------------------------
        // Input file extension to be used and be sure of leading "*." and
        // wait until validated.
        public void extensionTextBox_KeyDown(object sender, KeyEventArgs e)
        {
            extension = extensionTextBox.Text; // input latest text
            if (e.KeyCode == Keys.Enter)       // all chars entered
            {   // edit entered extension
                char[] chars  = new char[extension.Length];
                chars = extension.ToCharArray();
                if (chars[0].Equals('*') && chars[1].Equals('.'))
                { // both leading characters in string
                }
                else if (!chars[0].Equals('.'))
                { // no leading '.' so add it
                    extension = "." + extension;
                    if (!chars[0].Equals('*'))
                    { //--->>> this not going to work???
                        extension = "*" + extension;
                    }
                }
                else
                { // leading '.' so add leading '*'
                    extension = "*" + extension;
                }

                extensionTextBox.Text = extension; // display what will be used
                buttonOK.Visible = true; // to allow validation of the extension wanted
            } // end if (e.KeyCode == Keys.Enter)

        } // end event handler extensionTextBox_KeyDown

        //----------------------------------------------------------------------
        private void folderListBox_SelectedIndexChanged(object sender, EventArgs e)
        {
        } // end event handler folderListBox_SelectedIndexChanged

        private void CompareStatus_Click(object sender, EventArgs e)
        {
        } // end event handler CompareStatus_Click

        //----------------------------------------------------------------------
        // Obtain the selected extension and display and wait until validated.
        private void extensionComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            int index = extensionComboBox.SelectedIndex;
            extension = extensions[index];
            extensionTextBox.Text = extension; // display what will be used
            buttonOK.Visible = true; // to allow validation of the extension wanted
        } // end event handler extensionComboBox_SelectedIndexChanged

        //----------------------------------------------------------------------
        // Obtain the selected option and open append or open create as requested.
        private void existingReport_SelectedIndexChanged(object sender, EventArgs e)
        {
            int index = existingReport.SelectedIndex;
            if (index == 0) // Append
            {
                duplicatesReport = File.Open(duplicatesReportFileName, FileMode.Append,
                                             FileAccess.Write);
            }
            else
            {
                duplicatesReport = File.Open(duplicatesReportFileName, FileMode.Create,
                                             FileAccess.Write);
            }
            existingReport.Visible = false;

            // Compare the selected files.
            CompareFiles();

        } // end event handler existingReport_SelectedIndexChanged

        //----------------------------------------------------------------------
        // Class variables

        // File extension to use for files to be compared
        string extension = "";
        string[] extensions = new string[] { "*.jpg", "*.bmp", "*.doc", "*.txt" };

        string[] reportOptions = new string[] { "Append", "Overwrite" };

        const int maxFolders = 15;
        const int maxDuplicates = 300;
        string crNL = null;

        string fileError = "";

        public struct FolderFile
        {
            public IEnumerable<System.IO.FileInfo> list; // list of file names
            public string name;            // folder name
            public bool searched;          // whether folder has been searched
   
            public FolderFile(string name, IEnumerable<System.IO.FileInfo> list)
            {   // add new folder name and its file list to the structure
                this.name = name;
                this.list = list;
                this.searched = false;
            } // end constructor
        }

        // Files of the currently selected folder
        private int defaultIndex = -1;
        private int defaultCount = 0;
        private string[] defaultFiles = null; //string[];
        public struct DuplicateFile
        {
            private string name1;
            public string name2;
            public DuplicateFile(string name1, string name2)
            {   // add new pair of duplicated files to the structure
                this.name1 = name1;
                this.name2 = name2;
            }
        }

        // Number of selected folders and array of selected folders
        private int folderCount = 0;
        private FolderFile[] folderFile = new FolderFile[maxFolders];

        // Number of compared file pairs
        private int comparedCount = 0;

        // Number of duplicate file pairs and array containing them
        private bool maxDuplicatesDisplayed = false;
        public int duplicateCount = 0;
        public DuplicateFile[] duplicateFiles = new DuplicateFile[maxDuplicates];
       
        // Disk file text writer of the duplicate file pairs to examine when finished
        private int duplicatesReported = 0;
        private string duplicatesReportFileName = "";
        static private FileStream duplicatesReport = null;

    } // end class Form1

} // end namespace Compare

Saturday, February 11, 2012

Using Visual C# 2010 Express to Check Multiple Folders for Duplicate Files


Using Visual C# 2010 Express to Check Multiple Folders for Duplicate Files

 At the request of my son, I have written an application to allow the selection of multiple folders in which files can compared to determine which are duplicates.  This because he couldn't find such an application that compared photo files in more than one folder.

Due to ease of use I wrote it with Microsoft Visual C# 2010 Express.  The actual compare routine was lifted from an example on the Microsoft site.  Except that its initial check for the same file name was moved out of the routine since the supplied file names include the complete path name and can't be other than the same file rather than a duplicate. 

Also, I came across exceptions when attempting to open particular files in the compare routine.  So I added a check for whether the problem had already been reported.  If so, the file is just bypassed to avoid reporting the problem over and over. 

This problem occurred when attempting to compare a file with those in a subfolder of a selected folder.  These files were all read-only.  First, it was unexpected that the files of the subfolder would be included in the list of files of the folder so it remains to be determined if such files are correctly compared although I assume that they would be if it hadn't been for the read-only problem.  In addition, I need to look into the Microsoft method's Open to determine if it is Read/Write when only Read is needed since the file isn't going to be changed.

Summary

When the application is launched, a Windows form is displayed that has both a text box and a combo box in which the file extension of the files to be compared can be entered.  After an extension has been selected an OK button will be displayed to allow the extension to be changed.

After OK is clicked, a standard Windows Browse for Folder popup will be displayed to allow the selection of the first folder to be searched for a list of files with the extension.  After a selection is OKed, another folder can be selected, etc.  Each selected folder will be displayed in the list box as it is selected. 

When all the desired folders have been selected, Cancel will indicate that ready to begin the compares.  Then Please wait text will appear as the files of the selected folders with the selected extension are compared.  The duplicate files will be reported in a text file named DuplicateFiles.txt that will be created in the folder that was selected first.  When all files have been compared, text will be displayed indicating the number of duplicated files that has been found with an OK button to allow the number to be observed before the application is closed.

If a non-empty file named DuplicateFiles.txt is already in the initially selected folder, the choice can be made as to whether to append new duplicates to the file or overwrite the existing file.

The compare is done beginning with the first file with the extension in the list of all such files of the initial folder.  This file is then compared with each of the other files in the list and then with each of the files in the other selected folders so that any of its duplicates will be reported in order in the DuplicateFiles.txt file.  The next non-duplicate file in the initial folder list is then selected and compared the same way.  After the last file of the initial folder list has been compared to the files of the other folders, the first file of the second list is compared with the other files of its list that haven't already been marked as a duplicate file.  And so on until all files of all the selected folder lists have been compared with the remaining files.

The duplicate files are reported in pairs with the chosen file reported first and any file found to be its duplicate reported second with each such pair in a separate line of the text file.  Therefore, all files that are duplicates of the chosen file are reported in sequence with their complete path name before a new file name appears on the left side of a line.

Code

1) Program.cs as created by Visual C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;
namespace Compare
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        } // end method Main
     } // end method Program
} // end namespace Compare

2) Form1.Designer.cs as created by Visual C#

namespace Compare
{
    partial class Form1
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
        #region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.label1 = new System.Windows.Forms.Label();
            this.extensionTextBox = new System.Windows.Forms.TextBox();
            this.folderBrowserDialog1 = new System.Windows.Forms.FolderBrowserDialog();
            this.folderBrowserDialog2 = new System.Windows.Forms.FolderBrowserDialog();
            this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
            this.openFileDialog2 = new System.Windows.Forms.OpenFileDialog();
            this.buttonOK = new System.Windows.Forms.Button();
            this.folderListBox = new System.Windows.Forms.ListBox();
            this.extensionComboBox = new System.Windows.Forms.ComboBox();
            this.label2 = new System.Windows.Forms.Label();
            this.label3 = new System.Windows.Forms.Label();
            this.label4 = new System.Windows.Forms.Label();
            this.label5 = new System.Windows.Forms.Label();
            this.pleaseWait = new System.Windows.Forms.Label();
            this.numberDuplicates = new System.Windows.Forms.Label();
            this.doneButton = new System.Windows.Forms.Button();
            this.existingReport = new System.Windows.Forms.ComboBox();
            this.SuspendLayout();
            //
            // label1
            //
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(28, 32);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(97, 13);
            this.label1.TabIndex = 0;
            this.label1.Text = "extension (*.jpg, ...)";
            //
            // extensionTextBox
            //
            this.extensionTextBox.Location = new System.Drawing.Point(131, 28);
            this.extensionTextBox.Name = "extensionTextBox";
            this.extensionTextBox.Size = new System.Drawing.Size(71, 20);
            this.extensionTextBox.TabIndex = 1;
            this.extensionTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.extensionTextBox_KeyDown);
            //
            // openFileDialog1
            //
            this.openFileDialog1.FileName = "openFileDialog1";
            //
            // openFileDialog2
            //
            this.openFileDialog2.FileName = "openFileDialog2";
            //
            // buttonOK
            //
            this.buttonOK.Location = new System.Drawing.Point(208, 42);
            this.buttonOK.Name = "buttonOK";
            this.buttonOK.Size = new System.Drawing.Size(43, 23);
            this.buttonOK.TabIndex = 4;
            this.buttonOK.Text = "OK";
            this.buttonOK.UseVisualStyleBackColor = true;
            this.buttonOK.Visible = false;
            this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click);
            //
            // folderListBox
            //
            this.folderListBox.FormattingEnabled = true;
            this.folderListBox.Location = new System.Drawing.Point(31, 118);
            this.folderListBox.Name = "folderListBox";
            this.folderListBox.Size = new System.Drawing.Size(458, 225);
            this.folderListBox.TabIndex = 5;
            this.folderListBox.SelectedIndexChanged += new System.EventHandler(this.folderListBox_SelectedIndexChanged);
            //
            // extensionComboBox
            //
            this.extensionComboBox.FormattingEnabled = true;
            this.extensionComboBox.Location = new System.Drawing.Point(131, 54);
            this.extensionComboBox.Name = "extensionComboBox";
            this.extensionComboBox.Size = new System.Drawing.Size(71, 21);
            this.extensionComboBox.TabIndex = 6;
            this.extensionComboBox.Text = "Extension";
            this.extensionComboBox.SelectedIndexChanged += new System.EventHandler(this.extensionComboBox_SelectedIndexChanged);
            //
            // label2
            //
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(99, 62);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(16, 13);
            this.label2.TabIndex = 7;
            this.label2.Text = "or";
            //
            // label3
            //
            this.label3.AutoSize = true;
            this.label3.Location = new System.Drawing.Point(29, 102);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(86, 13);
            this.label3.TabIndex = 8;
            this.label3.Text = "Selected Folders";
            //
            // label4
            //
            this.label4.AutoSize = true;
            this.label4.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
            this.label4.Location = new System.Drawing.Point(316, 76);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(147, 13);
            this.label4.TabIndex = 9;
            this.label4.Text = "Duplicate files are reported in ";
            this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
            //
            // label5
            //
            this.label5.AutoSize = true;
            this.label5.Location = new System.Drawing.Point(316, 89);
            this.label5.Name = "label5";
            this.label5.Size = new System.Drawing.Size(154, 13);
            this.label5.TabIndex = 10;
            this.label5.Text = "DuplicateFiles.txt of initial folder";
            //
            // pleaseWait
            //
            this.pleaseWait.AutoSize = true;
            this.pleaseWait.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
            this.pleaseWait.Location = new System.Drawing.Point(319, 31);
            this.pleaseWait.Name = "pleaseWait";
            this.pleaseWait.Size = new System.Drawing.Size(170, 13);
            this.pleaseWait.TabIndex = 11;
            this.pleaseWait.Text = "Please Wait - Compare in Progress";
            this.pleaseWait.UseWaitCursor = true;
            this.pleaseWait.Visible = false;
            //
            // numberDuplicates
            //
            this.numberDuplicates.AutoSize = true;
            this.numberDuplicates.Location = new System.Drawing.Point(319, 52);
            this.numberDuplicates.Name = "numberDuplicates";
            this.numberDuplicates.Size = new System.Drawing.Size(156, 13);
            this.numberDuplicates.TabIndex = 12;
            this.numberDuplicates.Text = "Number of duplicate files is xxxx";
            this.numberDuplicates.Visible = false;
            //
            // doneButton
            //
            this.doneButton.Location = new System.Drawing.Point(278, 47);
            this.doneButton.Name = "doneButton";
            this.doneButton.Size = new System.Drawing.Size(35, 23);
            this.doneButton.TabIndex = 13;
            this.doneButton.Text = "OK";
            this.doneButton.UseVisualStyleBackColor = true;
            this.doneButton.Visible = false;
            this.doneButton.Click += new System.EventHandler(this.doneButton_Click);
            //
            // existingReport
            //
            this.existingReport.FormattingEnabled = true;
            this.existingReport.Location = new System.Drawing.Point(131, 81);
            this.existingReport.Name = "existingReport";
            this.existingReport.Size = new System.Drawing.Size(143, 21);
            this.existingReport.TabIndex = 14;
            this.existingReport.Text = "Existing DuplicateFiles.txt";
            this.existingReport.Visible = false;
            this.existingReport.SelectedIndexChanged += new System.EventHandler(this.existingReport_SelectedIndexChanged);
            //
            // Form1
            //
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(531, 362);
            this.Controls.Add(this.existingReport);
            this.Controls.Add(this.doneButton);
            this.Controls.Add(this.numberDuplicates);
            this.Controls.Add(this.pleaseWait);
            this.Controls.Add(this.label5);
            this.Controls.Add(this.label4);
            this.Controls.Add(this.label3);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.extensionComboBox);
            this.Controls.Add(this.folderListBox);
            this.Controls.Add(this.buttonOK);
            this.Controls.Add(this.extensionTextBox);
            this.Controls.Add(this.label1);
            this.Name = "Form1";
            this.Text = "Compare Files - Find duplicates for a particular extension in selected folders";
            this.ResumeLayout(false);
            this.PerformLayout();
        }
        #endregion

        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.TextBox extensionTextBox;
        private System.Windows.Forms.FolderBrowserDialog folderBrowserDialog1;
        private System.Windows.Forms.FolderBrowserDialog folderBrowserDialog2;
        private System.Windows.Forms.OpenFileDialog openFileDialog1;
        private System.Windows.Forms.OpenFileDialog openFileDialog2;
        private System.Windows.Forms.Button buttonOK;
        private System.Windows.Forms.ListBox folderListBox;
        private System.Windows.Forms.ComboBox extensionComboBox;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.Label label3;
        private System.Windows.Forms.Label label4;
        private System.Windows.Forms.Label label5;
        private System.Windows.Forms.Label pleaseWait;
        private System.Windows.Forms.Label numberDuplicates;
        private System.Windows.Forms.Button doneButton;
        private System.Windows.Forms.ComboBox existingReport;
    }
}

3) Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Compare
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            // (Mostly) generated control initialization.
            InitializeComponent();
            // Add selections to the combo boxes.
            extensionComboBox.MaxDropDownItems = 4;
            extensionComboBox.Items.Add(extensions[0]);
            extensionComboBox.Items.Add(extensions[1]);
            extensionComboBox.Items.Add(extensions[2]);
            extensionComboBox.Items.Add(extensions[3]);
            existingReport.MaxDropDownItems = 2;
            existingReport.Items.Add(reportOptions[0]);
            existingReport.Items.Add(reportOptions[1]);
            // Create string from byte arrays to get new lines in the duplicates file.
            Byte[] cR = new Byte[] { 13 };
            Byte[] lF = new Byte[] { 10 };
            crNL = Encoding.ASCII.GetString(cR) + Encoding.ASCII.GetString(lF);
        }
        //----------------------------------------------------------------------
        // Compare files in the selected folders.
        private void CompareFiles()
        {
            // Compare files of all folders starting with first file of first folder
            // to compare with the other files of that folder and then those of the
            // other folders.  Then proceed to the next file of the first folder and
            // repeat.  Then to the first file of the next folder to check the files
            // of that folder and the remaining folders.  And repeat.
            for (int f = 0; f < folderCount; f++) // Check folders for those not yet
            {                                     //  completely compared
                // Select initial default folder and list.
                int defaultFolder = f;
                IEnumerable<System.IO.FileInfo> defaultList = folderFile[defaultFolder].list;
                // Ignore list if no files with selected extension.
                if (defaultList.Count() > 0)
                {
                    string defaultFileName = defaultList.First().FullName;
                    // Compare particular file in the list to the other files of the list
                    // and the other lists (if not already in the duplicate table).
                    foreach (var v in folderFile[f].list)
                    {
                        // Ignore file if already found as a duplicate.
                        if (!InDuplicateTable(defaultFileName))
                        {   // Select the file and find any duplicates.
                            defaultFileName = v.FullName;
                            CompareSelectedFile(defaultFolder, defaultFileName);
                        }
                    } // end loop for each file in current list
                } // end if
                // Indicate that the folder has been searched.
                folderFile[f].searched = true;
            } // end loop thru selected folders
            // Hide Please Wait.
            pleaseWait.Visible = false;
            // Output count of duplicate files.
            //    duplicatesReport.WriteLine("Number of duplicate files is " + duplicateCount);
            Byte[] text = new UTF8Encoding(true).GetBytes("Number of duplicate files is "
                + duplicateCount + crNL);
            duplicatesReport.Write(text, 0, text.Length);
            duplicatesReport.Flush();
            numberDuplicates.Text = "Number of duplicate files is " + duplicateCount;
            numberDuplicates.Visible = true;
            // Display Done OK button to allow user to see number of duplicate files.
            // When clicked, the application will be terminated.
            doneButton.Visible = true;
       
        } // end method CompareFiles

        //----------------------------------------------------------------------
        // Obtain folder names and display in list box and open report file.
        private void ObtainFolderNames(string ext) // ext is selected file extension
        {
            string folder = "";
            bool selectFolder = true;
            System.IO.DirectoryInfo[] dir = new DirectoryInfo[maxFolders];
            // Do not allow the user to create new files via the FolderBrowserDialog.
            folderBrowserDialog1.ShowNewFolderButton = false;
            // Obtain folders to be searched for duplicate files with the
            // selected extension.
            while (selectFolder && folderCount < dir.Length)
            {
                if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
                {
                    folder = folderBrowserDialog1.SelectedPath;
                    // Check that folder not already selected.
                    bool newFolder = true;
                    for (int f = 0; f < folderCount; f++)
                    {
                        if (folder.Equals(folderFile[f].name))
                        {
                            newFolder = false;
                            break;
                        }
                    }
                    if (newFolder)
                    {
                        folderListBox.Items.Add(folder);
                        folderListBox.Refresh();
                        dir[folderCount] = new System.IO.DirectoryInfo(folder);
                        IEnumerable<System.IO.FileInfo> folderList =
                            dir[folderCount].GetFiles(ext,
                                                      System.IO.SearchOption.AllDirectories);
                        folderFile[folderCount] = new FolderFile(folder, folderList);
                        folderCount++;
                    } // end if (newFolder)
                }
                else
                {
                    selectFolder = false;
                }
            } // end select folders loop
            folderListBox.Refresh();
            // Quit if nothing selected.
            if (folderCount == 0)
            {
                Console.WriteLine("ERROR: no folders selected");
                this.Close(); // close form
                return;
            }
            // Display Please Wait.
            pleaseWait.Visible = true;
            pleaseWait.Refresh();
            // Open disk file to report duplicates.  Check if already available
            // and, if so, ask if to overwrite or add new entries at the end. 
            // If not available, create the file.
            duplicatesReportFileName = folderFile[0].name + "\\DuplicateFiles.txt";
            try
            {
                duplicatesReport = File.Open(duplicatesReportFileName,
                                             FileMode.Open, FileAccess.Read);
                long size = duplicatesReport.Length;
                if (size > 0)
                {
                    duplicatesReport.Close();
                    existingReport.Visible = true;
                    existingReport.Refresh();
                    return; // allow append or overwrite to be selected
                }
                else
                {
                    duplicatesReport.Close();
                    duplicatesReport = File.Open(duplicatesReportFileName,
                                                 FileMode.Append, FileAccess.Write);
                }
            }
            catch (Exception ex)
            {
                 duplicatesReport = File.Open(duplicatesReportFileName,
                                              FileMode.CreateNew, FileAccess.Write);
            }
            // Compare the selected files.
            CompareFiles();
        } // end method ObtainFolderNames
        //----------------------------------------------------------------------
        // Compare particular file in the list to the other files of the list
        // and the other lists.
        private void CompareSelectedFile(int selectedFolder, string selectedFileName)
        {
            for (int f = 0; f < folderCount; f++) // Check folders for those not
            {                                     //  yet completely compared
                if (!folderFile[f].searched)
                {
                    foreach (var v in folderFile[f].list)
                    {
                        string sss = v.FullName; //shows which items end up in result list
                        if ((f == selectedFolder) && (v.FullName.Equals(selectedFileName)))
                        { // Can't be duplicate with same name in same folder; must be
                          // the selected file
                        }
                        else // either different folder or different file of the folder
                        { // compare the selected file with the file of the list
                            if (FileCompare(selectedFileName, v.FullName))
                            {   // add file pair to duplicate array
                                if (duplicateCount < maxDuplicates)
                                {
                                    duplicateFiles[duplicateCount] =
                                        new DuplicateFile(selectedFileName, v.FullName);
                                    duplicateCount++;
                                }
                                else
                                {
                                    MessageBox.Show("ERROR: Maximum number of duplicates of "
                                                     + maxDuplicates + " exceeded");
                                }
                                Byte[] text = new UTF8Encoding(true).GetBytes(selectedFileName
                                    + " " + v.FullName + crNL);
                                duplicatesReport.Write(text, 0, text.Length);
                                duplicatesReport.Flush();
                            } // end if
                        } // end if check for the default file
                    } // end foreach
                } // end if
            } // end for loop over folders
        } // end method CompareSelectedFile
        //----------------------------------------------------------------------
        // Return true if file is in the duplicate table. 
        // Note: The name1 column is for the default file for which duplicates
        //       have been found.  The file passed is for a newly chosen file
        //       so could only be a file in the name2 column.
        private bool InDuplicateTable(string file)
        {
            for (int i = 0; i < duplicateCount; i++)
            {
                if (file.Equals(duplicateFiles[i].name2))
                {
                    return true;
                }
            }
            return false;
        } // end function InDuplicateTable
        //----------------------------------------------------------------------
        // This method accepts two strings the represent two files to
        // compare. A return value of 0 indicates that the contents of the files
        // are the same. A return value of any other value indicates that the
        // files are not the same.
        // Notes: This method is slightly modified from a Microsoft example.
        private bool FileCompare(string file1, string file2)
        {
            int file1byte;
            int file2byte;
            FileStream fs1 = null;
            FileStream fs2 = null;
              
            // Open the two files.
            try
            {
                fs1 = new FileStream(file1, FileMode.Open);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error: Unable to open first file " + file1 + " " + ex.Message);
            }
            try
            {
                fs2 = new FileStream(file2, FileMode.Open);
            }
            catch (Exception ex)
            {
                if (ex.Message.StartsWith("Access to the path") &&
                     fileError.StartsWith("Access to the path"))
                { // bypass the reporting of the exception and the compare
                }
                else
                {
                    fileError = ex.Message;
                    MessageBox.Show("Error: Unable to open second file " + file2 + " "
                        + ex.Message + " Further such errors will be ignored.");
                }
            }
            if ((fs1 == null) || (fs2 == null))
            {
                if (fs1 == null)
                {
                    if (fs2 != null)
                        fs2.Close();
                }
                if (fs2 == null)
                {
                    if (fs1 != null)
                        fs1.Close();
                }
                // Return false to indicate files are different
                return false;
            }
            // Check the file sizes. If they are not the same, the files
            // are not the same.
            if (fs1.Length != fs2.Length)
            {
                // Close the file
                fs1.Close();
                fs2.Close();
                // Return false to indicate files are different
                return false;
            }
            // Read and compare a byte from each file until either a
            // non-matching set of bytes is found or until the end of
            // file1 is reached.
            do
            {
                // Read one byte from each file.
                file1byte = fs1.ReadByte();
                file2byte = fs2.ReadByte();
            }
            while ((file1byte == file2byte) && (file1byte != -1));
    
            // Close the files.
            fs1.Close();
            fs2.Close();
            // Return the success of the comparison. "file1byte" is
            // equal to "file2byte" at this point only if the files are
            // the same.
            return ((file1byte - file2byte) == 0);
        } // end function FileCompare
        //----------------------------------------------------------------------
        // Event handlers
        // Hide OK button and then select the folders of the files to be
        // compared and do the compare.
        private void buttonOK_Click(object sender, EventArgs e)
        {
            buttonOK.Visible = false;
            ObtainFolderNames(extension);

        } // end event handler buttonOK_Click
        //----------------------------------------------------------------------
        // Allow operator to terminate
        private void doneButton_Click(object sender, EventArgs e)
        {
            doneButton.Visible = false;
            this.Close(); // close form
            return; // finished running
        } // end event handler doneButton_Click
        //----------------------------------------------------------------------
        // Input file extension to be used and be sure of leading "*." and
        // wait until validated.
        public void extensionTextBox_KeyDown(object sender, KeyEventArgs e)
        {
            extension = extensionTextBox.Text; // input latest text
            if (e.KeyCode == Keys.Enter)       // all chars entered
            {   // edit entered extension
                char[] chars  = new char[extension.Length];
                chars = extension.ToCharArray();
                if (chars[0].Equals('*') && chars[1].Equals('.'))
                { // both leading characters in string
                }
                else if (!chars[0].Equals('.'))
                { // no leading '.' so add it
                    extension = "." + extension;
                    if (!chars[0].Equals('*'))
                    { //--->>> this not going to work???
                        extension = "*" + extension;
                    }
                }
                else
                { // leading '.' so add leading '*'
                    extension = "*" + extension;
                }
                extensionTextBox.Text = extension; // display what will be used
                buttonOK.Visible = true; // to allow validation of the extension wanted
            } // end if (e.KeyCode == Keys.Enter)
        } // end event handler extensionTextBox_KeyDown
        //----------------------------------------------------------------------
        private void folderListBox_SelectedIndexChanged(object sender, EventArgs e)
        {
        } // end event handler folderListBox_SelectedIndexChanged
        //----------------------------------------------------------------------
        // Obtain the selected extension and display and wait until validated.
        private void extensionComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            int index = extensionComboBox.SelectedIndex;
            extension = extensions[index];
            extensionTextBox.Text = extension; // display what will be used
            buttonOK.Visible = true; // to allow validation of the extension wanted
        } // end event handler extensionComboBox_SelectedIndexChanged

        //----------------------------------------------------------------------
        // Obtain the selected option and open append or open create as requested.
        private void existingReport_SelectedIndexChanged(object sender, EventArgs e)
        {
            int index = existingReport.SelectedIndex;
            if (index == 0) // Append
            {
                duplicatesReport = File.Open(duplicatesReportFileName, FileMode.Append,
                                             FileAccess.Write);
            }
            else
            {
                duplicatesReport = File.Open(duplicatesReportFileName, FileMode.Create,
                                             FileAccess.Write);
            }
            existingReport.Visible = false;
            // Compare the selected files.
            CompareFiles();
        } // end event handler existingReport_SelectedIndexChanged

        //----------------------------------------------------------------------
        // Class variables
        // File extension to use for files to be compared
        string extension = "";
        string[] extensions = new string[] { "*.jpg", "*.bmp", "*.doc", "*.txt" };
        string[] reportOptions = new string[] { "Append", "Overwrite" };
        const int maxFolders = 15;
        const int maxDuplicates = 300;
        string crNL = null;
        string fileError = "";
        public struct FolderFile
        {
            public IEnumerable<System.IO.FileInfo> list; // list of file names
            public string name;            // folder name
            public bool searched;          // whether folder has been searched
   
            public FolderFile(string name, IEnumerable<System.IO.FileInfo> list)
            {   // add new folder name and its file list to the structure
                this.name = name;
                this.list = list;
                this.searched = false;
            } // end constructor
        }
        public struct DuplicateFile
        {
            private string name1;
            public string name2;
            public DuplicateFile(string name1, string name2)
            {   // add new pair of duplicated files to the structure
                this.name1 = name1;
                this.name2 = name2;
            }
        }
        // Number of selected folders and array of selected folders
        private int folderCount = 0;
        private FolderFile[] folderFile = new FolderFile[maxFolders];
        // Number of duplicate file pairs and array containing them
        public int duplicateCount = 0;
        public DuplicateFile[] duplicateFiles = new DuplicateFile[maxDuplicates];
       
        // Disk file text writer of the duplicate file pairs to examine when finished
        private string duplicatesReportFileName = "";
        static private FileStream duplicatesReport = null;
    } // end class Form1

} // end namespace Compare