From 4fc7f9c17866950c6310b837cee228ffa3555ba0 Mon Sep 17 00:00:00 2001 From: Matthew Ahrenstein Date: Fri, 13 Mar 2015 22:58:22 -0400 Subject: [PATCH] Committing the project I wrote this on the train so I'm just committing it now that I'm home --- README.mediawiki | 12 ++ Windows Duplicate File Finder.sln | 30 +++ Windows Duplicate File Finder/App.config | 6 + Windows Duplicate File Finder/Program.cs | 35 ++++ .../Properties/AssemblyInfo.cs | 48 +++++ .../Properties/AssemblyVersion.cs | 54 +++++ .../Properties/Resources.Designer.cs | 63 ++++++ .../Properties/Resources.resx | 117 +++++++++++ .../Properties/Settings.Designer.cs | 26 +++ .../Properties/Settings.settings | 7 + .../WindowsDuplicateFileFinder.csproj | 106 ++++++++++ Windows Duplicate File Finder/frmAbout.cs | 71 +++++++ .../frmAbout.designer.cs | 115 +++++++++++ Windows Duplicate File Finder/frmAbout.resx | 120 ++++++++++++ .../frmMain.Designer.cs | 127 ++++++++++++ Windows Duplicate File Finder/frmMain.cs | 96 +++++++++ Windows Duplicate File Finder/frmMain.resx | 120 ++++++++++++ .../Properties/AssemblyInfo.cs | 36 ++++ .../WindowsDuplicateFileFinder.Common.csproj | 55 ++++++ .../clsCoreFunctions.cs | 184 ++++++++++++++++++ 20 files changed, 1428 insertions(+) create mode 100644 README.mediawiki create mode 100644 Windows Duplicate File Finder.sln create mode 100644 Windows Duplicate File Finder/App.config create mode 100644 Windows Duplicate File Finder/Program.cs create mode 100644 Windows Duplicate File Finder/Properties/AssemblyInfo.cs create mode 100644 Windows Duplicate File Finder/Properties/AssemblyVersion.cs create mode 100644 Windows Duplicate File Finder/Properties/Resources.Designer.cs create mode 100644 Windows Duplicate File Finder/Properties/Resources.resx create mode 100644 Windows Duplicate File Finder/Properties/Settings.Designer.cs create mode 100644 Windows Duplicate File Finder/Properties/Settings.settings create mode 100644 Windows Duplicate File Finder/WindowsDuplicateFileFinder.csproj create mode 100644 Windows Duplicate File Finder/frmAbout.cs create mode 100644 Windows Duplicate File Finder/frmAbout.designer.cs create mode 100644 Windows Duplicate File Finder/frmAbout.resx create mode 100644 Windows Duplicate File Finder/frmMain.Designer.cs create mode 100644 Windows Duplicate File Finder/frmMain.cs create mode 100644 Windows Duplicate File Finder/frmMain.resx create mode 100644 WindowsDuplicateFileFinder.Common/Properties/AssemblyInfo.cs create mode 100644 WindowsDuplicateFileFinder.Common/WindowsDuplicateFileFinder.Common.csproj create mode 100644 WindowsDuplicateFileFinder.Common/clsCoreFunctions.cs diff --git a/README.mediawiki b/README.mediawiki new file mode 100644 index 0000000..27cb852 --- /dev/null +++ b/README.mediawiki @@ -0,0 +1,12 @@ +=== Windows Duplicate File Finder === +The Windows Duplicate File Finder recursively searches the selected directory for duplicate files and saves the results to a text file on the user's desktop. + +=== How does it work? === +It works by recursively scanning a directory for all files. It them calculates the md5sum of the files, and checks for duplicates. This is done by storing the md5sums in a string based List object array, so it can be looped through to look for comparisons. + +=== Known issues === +*1) If you select a directory with hidden or system files (sadly such as %HOMEPATH%\Documents) you will get an access denied error +*2) All string arrays and string List objects are stored in memory, and the program has to iterate through them. The more files you have in the scanned directory, the longer this will take. Sadly I don't have a progress bar or indicator right now. A message dialog box will appear at the start and at the end of the scan. + +=== To Do === +*1) See repository issues at: https://github.com/ahrenstein/Windows-Duplicate-File-Finder/labels/enhancement diff --git a/Windows Duplicate File Finder.sln b/Windows Duplicate File Finder.sln new file mode 100644 index 0000000..de4714d --- /dev/null +++ b/Windows Duplicate File Finder.sln @@ -0,0 +1,30 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.31101.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsDuplicateFileFinder", "Windows Duplicate File Finder\WindowsDuplicateFileFinder.csproj", "{96EEB1D2-B8DE-4883-9929-89F8B726D6B3}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7467D725-9326-4BD0-81DE-79D251769A2D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsDuplicateFileFinder.Common", "WindowsDuplicateFileFinder.Common\WindowsDuplicateFileFinder.Common.csproj", "{8339A5A1-9839-4B5D-9276-D39A4710FEC6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {96EEB1D2-B8DE-4883-9929-89F8B726D6B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {96EEB1D2-B8DE-4883-9929-89F8B726D6B3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {96EEB1D2-B8DE-4883-9929-89F8B726D6B3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {96EEB1D2-B8DE-4883-9929-89F8B726D6B3}.Release|Any CPU.Build.0 = Release|Any CPU + {8339A5A1-9839-4B5D-9276-D39A4710FEC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8339A5A1-9839-4B5D-9276-D39A4710FEC6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8339A5A1-9839-4B5D-9276-D39A4710FEC6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8339A5A1-9839-4B5D-9276-D39A4710FEC6}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Windows Duplicate File Finder/App.config b/Windows Duplicate File Finder/App.config new file mode 100644 index 0000000..8e15646 --- /dev/null +++ b/Windows Duplicate File Finder/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Windows Duplicate File Finder/Program.cs b/Windows Duplicate File Finder/Program.cs new file mode 100644 index 0000000..c6878de --- /dev/null +++ b/Windows Duplicate File Finder/Program.cs @@ -0,0 +1,35 @@ +/* ---------------------------------------------------------------------- +// +// Copyright (c) 2015 Ahrenstein., All Rights Reserved. +// Authors: +// Matthew Ahrenstein 2015 @ahrenstein +// +// ---------------------------------------------------------------------- +// +// WindowsDuplicateFileFinder +// OPEN SOURCE PROJECT! Use is subject to license terms in LICENSE.txt +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace WindowsDuplicateFileFinder +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new frmMain()); + } + } +} diff --git a/Windows Duplicate File Finder/Properties/AssemblyInfo.cs b/Windows Duplicate File Finder/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..086e702 --- /dev/null +++ b/Windows Duplicate File Finder/Properties/AssemblyInfo.cs @@ -0,0 +1,48 @@ +/* ---------------------------------------------------------------------- +// +// Copyright (c) 2015 Ahrenstein., All Rights Reserved. +// Authors: +// Matthew Ahrenstein 2015 @ahrenstein +// +// ---------------------------------------------------------------------- +// +// WindowsDuplicateFileFinder +// OPEN SOURCE PROJECT! Use is subject to license terms in LICENSE.txt +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +*/ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Windows Duplicate File Finder")] +[assembly: AssemblyDescription("A tool that uses MD5 sums to find duplicate files in a scanned directory")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Ahrenstein")] +[assembly: AssemblyProduct("Windows Duplicate File Finder")] +[assembly: AssemblyCopyright("Copyright © Ahrenstein 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("df971024-d68e-406b-8fa6-02acaebd43b2")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Windows Duplicate File Finder/Properties/AssemblyVersion.cs b/Windows Duplicate File Finder/Properties/AssemblyVersion.cs new file mode 100644 index 0000000..32228fa --- /dev/null +++ b/Windows Duplicate File Finder/Properties/AssemblyVersion.cs @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2014 Nevec Networks LLC., All Rights Reserved. + * INTERNAL/PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + */ +using System; +using System.Reflection; + +namespace WindowsDuplicateFileFinder +{ + /// + /// Static class to build the engine version string. + /// + public class AssemblyVersion + { + /** + * Fields + */ + public static string _NAME; + public static string _VERSION; + public static string _BUILD; + public static string _BUILD_DATE; + public static string _COPYRIGHT; + +#if DEBUG + public static string _DEBUG = "DEBUG_BUILD"; +#else + public static string _DEBUG = ""; +#endif + public static string _VERSION_STRING; + + /** + * Methods + */ + /// + /// Initializes static members of the AssemblyVersion class. + /// + static AssemblyVersion() + { + Assembly asm = Assembly.GetExecutingAssembly(); + AssemblyProductAttribute asmProd = asm.GetCustomAttributes(typeof(AssemblyProductAttribute), false)[0] as AssemblyProductAttribute; + AssemblyDescriptionAttribute asmDesc = asm.GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false)[0] as AssemblyDescriptionAttribute; + AssemblyCopyrightAttribute asmCopyright = asm.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false)[0] as AssemblyCopyrightAttribute; + DateTime buildDate = new DateTime(2000, 1, 1).AddDays(asm.GetName().Version.Build).AddSeconds(asm.GetName().Version.Revision * 2); + _NAME = asmProd.Product; + _VERSION = asm.GetName().Version.Major + "." + asm.GetName().Version.Minor + "." + asm.GetName().Version.Revision; + _BUILD = string.Empty + asm.GetName().Version.Build; + _BUILD_DATE = buildDate.ToShortDateString() + " @ " + buildDate.ToShortTimeString(); + _COPYRIGHT = asmCopyright.Copyright; + + _VERSION_STRING = AssemblyVersion._NAME + " " + AssemblyVersion._DEBUG + " " + AssemblyVersion._VERSION + " build " + AssemblyVersion._BUILD; + } + } // public class AssemblyVersion +} // namespace SecurePassword.GeneratorLite diff --git a/Windows Duplicate File Finder/Properties/Resources.Designer.cs b/Windows Duplicate File Finder/Properties/Resources.Designer.cs new file mode 100644 index 0000000..cb0e61c --- /dev/null +++ b/Windows Duplicate File Finder/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34014 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace WindowsDuplicateFileFinder.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WindowsDuplicateFileFinder.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Windows Duplicate File Finder/Properties/Resources.resx b/Windows Duplicate File Finder/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/Windows Duplicate File Finder/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Windows Duplicate File Finder/Properties/Settings.Designer.cs b/Windows Duplicate File Finder/Properties/Settings.Designer.cs new file mode 100644 index 0000000..92af2cf --- /dev/null +++ b/Windows Duplicate File Finder/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34014 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace WindowsDuplicateFileFinder.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Windows Duplicate File Finder/Properties/Settings.settings b/Windows Duplicate File Finder/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/Windows Duplicate File Finder/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Windows Duplicate File Finder/WindowsDuplicateFileFinder.csproj b/Windows Duplicate File Finder/WindowsDuplicateFileFinder.csproj new file mode 100644 index 0000000..229e219 --- /dev/null +++ b/Windows Duplicate File Finder/WindowsDuplicateFileFinder.csproj @@ -0,0 +1,106 @@ + + + + + Debug + AnyCPU + {96EEB1D2-B8DE-4883-9929-89F8B726D6B3} + WinExe + Properties + WindowsDuplicateFileFinder + Windows Duplicate File Finder + v4.5 + 512 + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + Form + + + frmAbout.cs + + + Form + + + frmMain.cs + + + + + frmAbout.cs + + + frmMain.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + {8339a5a1-9839-4b5d-9276-d39a4710fec6} + WindowsDuplicateFileFinder.Common + + + + + \ No newline at end of file diff --git a/Windows Duplicate File Finder/frmAbout.cs b/Windows Duplicate File Finder/frmAbout.cs new file mode 100644 index 0000000..0dc102d --- /dev/null +++ b/Windows Duplicate File Finder/frmAbout.cs @@ -0,0 +1,71 @@ +/* ---------------------------------------------------------------------- +// +// Copyright (c) 2015 Ahrenstein., All Rights Reserved. +// Authors: +// Matthew Ahrenstein 2015 @ahrenstein +// +// ---------------------------------------------------------------------- +// +// WindowsDuplicateFileFinder +// OPEN SOURCE PROJECT! Use is subject to license terms in LICENSE.txt +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +*/ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using System.Reflection; // used for grabbing Assembly info to make a nice About Box + +namespace WindowsDuplicateFileFinder +{ + /// + /// Implements the logic code for the about box. + /// + public partial class frmAbout : Form + { + /** + * Methods + */ + /// + /// Initializes a new instance of the class. + /// + public frmAbout() + { + string[] projectDescription = new string[] + { + "Windows Duplicate File Finder.", + "This program will recursively scan the selected directory for duplicate files", + "by checking and comparing the MD5 sums of all the found files.", + "Any duplicates will be saved to a text file list on the user's desktop", + "", + "\t\t*** Windows Duplicate File Finder Credits ***", + "Matthew Ahrenstein:", + "\t- Common Library (Contains Duplicate File Finder Code)", + "\t- User Interface", + "", + "Nevec Networks LLC:", + "\t- Assembly Attribute Accessors (Used to grab build/version info automatically)", + }; + + InitializeComponent(); + this.lblProjectName.Text = AssemblyVersion._NAME; + this.lblVersion.Text = "Version: " + AssemblyVersion._VERSION_STRING; + this.lblCopyright.Text = AssemblyVersion._COPYRIGHT; + this.txtDescription.Lines = projectDescription; + } + + /// + /// Event that occurs when the "Close" button is clicked. + /// + /// + /// + private void btnClose_Click(object sender, EventArgs e) + { + Close(); + } + } // public partial class frmAbout : Form +} // namespace SecurePassword.GeneratorLite diff --git a/Windows Duplicate File Finder/frmAbout.designer.cs b/Windows Duplicate File Finder/frmAbout.designer.cs new file mode 100644 index 0000000..cf0156c --- /dev/null +++ b/Windows Duplicate File Finder/frmAbout.designer.cs @@ -0,0 +1,115 @@ +namespace WindowsDuplicateFileFinder +{ + partial class frmAbout + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.lblProjectName = new System.Windows.Forms.Label(); + this.lblVersion = new System.Windows.Forms.Label(); + this.lblCopyright = new System.Windows.Forms.Label(); + this.txtDescription = new System.Windows.Forms.TextBox(); + this.btnClose = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // lblProjectName + // + this.lblProjectName.AutoSize = true; + this.lblProjectName.Location = new System.Drawing.Point(12, 10); + this.lblProjectName.Name = "lblProjectName"; + this.lblProjectName.Size = new System.Drawing.Size(99, 13); + this.lblProjectName.TabIndex = 0; + this.lblProjectName.Text = "projectName_Label"; + // + // lblVersion + // + this.lblVersion.AutoSize = true; + this.lblVersion.Location = new System.Drawing.Point(12, 30); + this.lblVersion.Name = "lblVersion"; + this.lblVersion.Size = new System.Drawing.Size(73, 13); + this.lblVersion.TabIndex = 1; + this.lblVersion.Text = "version_Label"; + // + // lblCopyright + // + this.lblCopyright.AutoSize = true; + this.lblCopyright.Location = new System.Drawing.Point(12, 50); + this.lblCopyright.Name = "lblCopyright"; + this.lblCopyright.Size = new System.Drawing.Size(82, 13); + this.lblCopyright.TabIndex = 2; + this.lblCopyright.Text = "copyright_Label"; + // + // txtDescription + // + this.txtDescription.Location = new System.Drawing.Point(15, 68); + this.txtDescription.Multiline = true; + this.txtDescription.Name = "txtDescription"; + this.txtDescription.ReadOnly = true; + this.txtDescription.Size = new System.Drawing.Size(407, 248); + this.txtDescription.TabIndex = 1; + this.txtDescription.TabStop = false; + this.txtDescription.Text = "Description"; + // + // btnClose + // + this.btnClose.Location = new System.Drawing.Point(167, 322); + this.btnClose.Name = "btnClose"; + this.btnClose.Size = new System.Drawing.Size(75, 23); + this.btnClose.TabIndex = 4; + this.btnClose.Text = "Close"; + this.btnClose.UseVisualStyleBackColor = true; + this.btnClose.Click += new System.EventHandler(this.btnClose_Click); + // + // frmAbout + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(434, 359); + this.Controls.Add(this.btnClose); + this.Controls.Add(this.txtDescription); + this.Controls.Add(this.lblCopyright); + this.Controls.Add(this.lblVersion); + this.Controls.Add(this.lblProjectName); + this.MaximizeBox = false; + this.MaximumSize = new System.Drawing.Size(450, 398); + this.MinimizeBox = false; + this.MinimumSize = new System.Drawing.Size(450, 398); + this.Name = "frmAbout"; + this.Text = "About Windows Duplicate File Finder"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label lblProjectName; + private System.Windows.Forms.Label lblVersion; + private System.Windows.Forms.Label lblCopyright; + private System.Windows.Forms.TextBox txtDescription; + private System.Windows.Forms.Button btnClose; + } +} \ No newline at end of file diff --git a/Windows Duplicate File Finder/frmAbout.resx b/Windows Duplicate File Finder/frmAbout.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/Windows Duplicate File Finder/frmAbout.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Windows Duplicate File Finder/frmMain.Designer.cs b/Windows Duplicate File Finder/frmMain.Designer.cs new file mode 100644 index 0000000..f010a47 --- /dev/null +++ b/Windows Duplicate File Finder/frmMain.Designer.cs @@ -0,0 +1,127 @@ +namespace WindowsDuplicateFileFinder +{ + partial class frmMain + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.btnQuit = new System.Windows.Forms.Button(); + this.lblPath = new System.Windows.Forms.Label(); + this.txtPath = new System.Windows.Forms.TextBox(); + this.btnPath = new System.Windows.Forms.Button(); + this.btnAbout = new System.Windows.Forms.Button(); + this.btnScan = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // btnQuit + // + this.btnQuit.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnQuit.Location = new System.Drawing.Point(497, 180); + this.btnQuit.Name = "btnQuit"; + this.btnQuit.Size = new System.Drawing.Size(75, 23); + this.btnQuit.TabIndex = 0; + this.btnQuit.Text = "Quit"; + this.btnQuit.UseVisualStyleBackColor = true; + this.btnQuit.Click += new System.EventHandler(this.btnQuit_Click); + // + // lblPath + // + this.lblPath.AutoSize = true; + this.lblPath.Location = new System.Drawing.Point(12, 55); + this.lblPath.Name = "lblPath"; + this.lblPath.Size = new System.Drawing.Size(221, 16); + this.lblPath.TabIndex = 1; + this.lblPath.Text = "What directory do you want to scan?"; + // + // txtPath + // + this.txtPath.Location = new System.Drawing.Point(12, 74); + this.txtPath.Name = "txtPath"; + this.txtPath.Size = new System.Drawing.Size(507, 22); + this.txtPath.TabIndex = 2; + this.txtPath.Text = "C:\\Users"; + // + // btnPath + // + this.btnPath.Location = new System.Drawing.Point(525, 74); + this.btnPath.Name = "btnPath"; + this.btnPath.Size = new System.Drawing.Size(32, 23); + this.btnPath.TabIndex = 3; + this.btnPath.Text = "..."; + this.btnPath.UseVisualStyleBackColor = true; + this.btnPath.Click += new System.EventHandler(this.btnPath_Click); + // + // btnAbout + // + this.btnAbout.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnAbout.Location = new System.Drawing.Point(416, 180); + this.btnAbout.Name = "btnAbout"; + this.btnAbout.Size = new System.Drawing.Size(75, 23); + this.btnAbout.TabIndex = 4; + this.btnAbout.Text = "About"; + this.btnAbout.UseVisualStyleBackColor = true; + this.btnAbout.Click += new System.EventHandler(this.btnAbout_Click); + // + // btnScan + // + this.btnScan.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.btnScan.Location = new System.Drawing.Point(12, 180); + this.btnScan.Name = "btnScan"; + this.btnScan.Size = new System.Drawing.Size(221, 23); + this.btnScan.TabIndex = 5; + this.btnScan.Text = "Scan Directory For Duplicates"; + this.btnScan.UseVisualStyleBackColor = true; + this.btnScan.Click += new System.EventHandler(this.btnScan_Click); + // + // frmMain + // + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(584, 215); + this.Controls.Add(this.btnScan); + this.Controls.Add(this.btnAbout); + this.Controls.Add(this.btnPath); + this.Controls.Add(this.txtPath); + this.Controls.Add(this.lblPath); + this.Controls.Add(this.btnQuit); + this.Name = "frmMain"; + this.Text = "Windows Duplicate File Finder"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button btnQuit; + private System.Windows.Forms.Label lblPath; + private System.Windows.Forms.TextBox txtPath; + private System.Windows.Forms.Button btnPath; + private System.Windows.Forms.Button btnAbout; + private System.Windows.Forms.Button btnScan; + } +} + diff --git a/Windows Duplicate File Finder/frmMain.cs b/Windows Duplicate File Finder/frmMain.cs new file mode 100644 index 0000000..2b31b29 --- /dev/null +++ b/Windows Duplicate File Finder/frmMain.cs @@ -0,0 +1,96 @@ +/* ---------------------------------------------------------------------- +// +// Copyright (c) 2015 Ahrenstein., All Rights Reserved. +// Authors: +// Matthew Ahrenstein 2015 @ahrenstein +// +// ---------------------------------------------------------------------- +// +// WindowsDuplicateFileFinder +// OPEN SOURCE PROJECT! Use is subject to license terms in LICENSE.txt +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +*/ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using WindowsDuplicateFileFinder.Common; + +namespace WindowsDuplicateFileFinder +{ + public partial class frmMain : Form + { + public frmMain() + { + InitializeComponent(); + // Set the default scan path to somewhere useful + txtPath.Text = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures); + } + /// + /// When clicked, this button quits the software by closing the main form + /// + /// + /// + private void btnQuit_Click(object sender, EventArgs e) + { + this.Close(); + } + + /// + /// When clicked, this button opens a select folder dialog box to allow the user to select the folder to scan + /// + /// + /// + private void btnPath_Click(object sender, EventArgs e) + { + // Create a Select Folder dialog box + FolderBrowserDialog fbd = new FolderBrowserDialog(); + + // Set the starting point to be the user's home folder + //fbd.RootFolder = Environment.SpecialFolder.UserProfile; + + // Ask for a path + fbd.ShowDialog(); + // Set the selected path as the text box text + txtPath.Text = fbd.SelectedPath.ToString(); + } + + /// + /// When clicked, this button opens the About dialog box + /// + /// + /// + private void btnAbout_Click(object sender, EventArgs e) + { + // Instantiate About Box + frmAbout about = new frmAbout(); + // Call About Box as a dialog + about.ShowDialog(); + } + + /// + /// When clicked, run the functions to scan for duplicates and save the list to the desktop + /// + /// + /// + private void btnScan_Click(object sender, EventArgs e) + { + // Instantiate the common library class + CoreFunctions core = new CoreFunctions(); + // Display a dialog box displaying where the output of the scan will be saved + string strFileToSaveResultsTo = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\DupeScan.txt"; + MessageBox.Show("Files will be saved to " + strFileToSaveResultsTo + "\n\nThis may take a while. Another message will appear when the scan is over.", "Starting Scan...", MessageBoxButtons.OK); + + // Perform the search using the Windows Duplicate File Finder Common Library + core.FindFileDuplicates(txtPath.Text, strFileToSaveResultsTo); + + // Show a dialog box to alert the user that the scan is over. + MessageBox.Show("The scan has now stopped. If no errors were shown, then all duplicates should be found.", "Scan Completed", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + } +} diff --git a/Windows Duplicate File Finder/frmMain.resx b/Windows Duplicate File Finder/frmMain.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/Windows Duplicate File Finder/frmMain.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/WindowsDuplicateFileFinder.Common/Properties/AssemblyInfo.cs b/WindowsDuplicateFileFinder.Common/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..dac5f4e --- /dev/null +++ b/WindowsDuplicateFileFinder.Common/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("WindowsDuplicateFileFinder.Common")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("WindowsDuplicateFileFinder.Common")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("2dbab1c7-fcac-43ac-b015-2537b0f51f8b")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/WindowsDuplicateFileFinder.Common/WindowsDuplicateFileFinder.Common.csproj b/WindowsDuplicateFileFinder.Common/WindowsDuplicateFileFinder.Common.csproj new file mode 100644 index 0000000..c3ac7fe --- /dev/null +++ b/WindowsDuplicateFileFinder.Common/WindowsDuplicateFileFinder.Common.csproj @@ -0,0 +1,55 @@ + + + + + Debug + AnyCPU + {8339A5A1-9839-4B5D-9276-D39A4710FEC6} + Library + Properties + WindowsDuplicateFileFinder.Common + WindowsDuplicateFileFinder.Common + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/WindowsDuplicateFileFinder.Common/clsCoreFunctions.cs b/WindowsDuplicateFileFinder.Common/clsCoreFunctions.cs new file mode 100644 index 0000000..1a760fc --- /dev/null +++ b/WindowsDuplicateFileFinder.Common/clsCoreFunctions.cs @@ -0,0 +1,184 @@ +/* ---------------------------------------------------------------------- +// +// Copyright (c) 2015 Ahrenstein., All Rights Reserved. +// Authors: +// Matthew Ahrenstein 2015 @ahrenstein +// +// ---------------------------------------------------------------------- +// +// WindowsDuplicateFileFinder.Common +// OPEN SOURCE PROJECT! Use is subject to license terms in LICENSE.txt +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +*/ +using System; +using System.IO; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Security.Cryptography; //For MD5 sum generation + +namespace WindowsDuplicateFileFinder.Common +{ + public class CoreFunctions + { + // This bool is set to true if GetFileList succeeds in the Try/Catch + bool FileListGathered = false; + + /// + /// Scan a path recursively for file duplicates via MD5 sum and save the duplicates to a file + /// + /// Directory to start recursive scan from + /// File to save results to + public void FindFileDuplicates(string pathToScan, string pathToSave) + { + // Scan for a list of files and save to a string array + string[] filesList = GetFileList(pathToScan); + + // If the GetFileList succeeds then continue with the rest of the application functions + if (FileListGathered == true) + { + // Instantiate a string List object for storing MD5 sums + List md5sums = new List(); + + // Loop through the file list and add MD5 sums to the string List object md5sums + foreach (string file in filesList) + { + md5sums.Add(GetMD5Sum(file)); + } + + // Instantiate a string List object and store the duplicate search results in it + List duplicates = DuplicateSearch(md5sums); + + // Save the duplicate search results to a file + SaveToFile(md5sums, duplicates, filesList, pathToSave); + } + + + } + /// + /// Get a list of files recursively from a starting path and store them in a string array + /// + /// Starting directory + /// String array of files found + string[] GetFileList(string startingPath) + { + // Declare a string to store the results in + string[] results = null; + // Try/Catch used to make sure file permissions errors don't crash the app + try + { + // Store the file scan results in the results array + results = Directory.GetFiles(startingPath, "*.*", SearchOption.AllDirectories); + // Set the FileListGathered bool to true to allow the rest of the functions to continue + FileListGathered = true; + // return the results + return results; + } + catch (Exception ex) // If an exception occurs, this will deal with it without crashing the app + { + // Display a message containing the exception + MessageBox.Show("Error: You probably tried scanning a folder with hidden/system files. \n\nError received from Windows:\n" + ex, "ERROR!", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + return results; + } + + /// + /// Generate the MD5 sum of the given file and return it as a string + /// + /// Complete path to file that the sum will be generated for + /// Lower case MD5 sum + static string GetMD5Sum(string file) + { + // Start the MD5 generation process + using (var sum = MD5.Create()) + // Read the bytes of the file we want the sum for + using (var stream = File.OpenRead(file)) + // Convert the stream to MD5 sum and make it a lower case string. Then return it + return BitConverter.ToString(sum.ComputeHash(stream)).Replace("-", "").ToLower(); + + } + + /// + /// Search a string List object of files for duplicate MD5 sums and return the results as a string List object + /// + /// string List object of MD5 sums to search for duplicates + /// string List object of duplicate MD5 sums + static List DuplicateSearch(List md5sums) + { + // Instantiate a string List for storing duplicates + List duplicates = new List(); + + // for every item in the duplicate list + for (int i = 0; i <= (md5sums.Count() -2); i++) + { + // for every item in the duplicate list 1 ahead of the parent for loop + for (int j = (i + 1); j <= (md5sums.Count() -2); j++) + { + // Compare the two items and add them to the list if they match + if (md5sums[i] == md5sums[j]) + { + // Only add them to the list if they aren't aleeady in it + if (!duplicates.Contains(md5sums[i])) + { + duplicates.Add(md5sums[i]); + } + } + } + } + // return the list of duplicates + return duplicates; + } + + /// + /// Save the list of duplicate MD5 sums to the specified file + /// + /// MD5 sums string List object to compare + /// string List object of known duplicates + /// string array of file paths + /// File to save output to + void SaveToFile(List md5sums, List duplicates, string[] files, string saveFile) + { + // Using a Try/Catch here to make sure we don't try to write null to the file + try + { + // Delete the old output file if it exists + if (File.Exists(saveFile)) + { + File.Delete(saveFile); + } + // Recreate and open the file for writing + StreamWriter file = File.CreateText(saveFile); + foreach (string dupeFile in duplicates) + { + // Write out the hash to a line in the file + file.WriteLine(dupeFile); + file.WriteLine("---------------------------------"); + + + //Write out the corresponding file paths for the duplicate + for (int i = 0; i <= (files.Length - 1); i++) + { + if (md5sums[i] == dupeFile) + { + file.WriteLine(files[i]); + } + } + // Write an empty line before continuing the next iteration + file.WriteLine(""); + } + + // Close the file once writing is done + file.Close(); + // The below line will create the scan results file if it doesn't exists (or overwrite it if it does) and insert the results + // File.WriteAllLines(saveFile, fileContents, Encoding.UTF8); + } + catch (Exception ex) // If an exception occurs, this will deal with it without crashing the app + { + // Display a message containing the exception + MessageBox.Show("Error!: Unable to save data to the results file. \n\nError received from Windows:\n" + ex, "ERROR!", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } +} \ No newline at end of file