changeset 0:8ac8eb805b6c default tip

Initial commit
author Ivo Smits <Ivo@UCIS.nl>
date Fri, 07 Feb 2014 23:23:08 +0100
parents
children
files .hgignore AutoCRCheck.csproj Program.cs Properties/AssemblyInfo.cs Properties/Resources.Designer.cs Properties/Resources.resx Properties/Settings.Designer.cs Properties/Settings.settings frmOptions.Designer.cs frmOptions.cs frmOptions.resx
diffstat 11 files changed, 867 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Fri Feb 07 23:23:08 2014 +0100
@@ -0,0 +1,3 @@
+syntax: glob
+bin/*
+obj/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AutoCRCheck.csproj	Fri Feb 07 23:23:08 2014 +0100
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{4B58106F-D9C6-4473-AD83-42ED98E9ECAC}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>AutoCRCheck</RootNamespace>
+    <AssemblyName>AutoCRCheck</AssemblyName>
+    <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <StartupObject>
+    </StartupObject>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="frmOptions.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="frmOptions.Designer.cs">
+      <DependentUpon>frmOptions.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <EmbeddedResource Include="frmOptions.resx">
+      <DependentUpon>frmOptions.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+    <None Include="Properties\Settings.settings">
+      <Generator>SettingsSingleFileGenerator</Generator>
+      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+    </None>
+    <Compile Include="Properties\Settings.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Settings.settings</DependentUpon>
+      <DesignTimeSharedInput>True</DesignTimeSharedInput>
+    </Compile>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Program.cs	Fri Feb 07 23:23:08 2014 +0100
@@ -0,0 +1,192 @@
+using System;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Windows.Forms;
+
+namespace AutoCRCheck {
+	static class Program {
+		static Boolean DeleteBad = false;
+		static String RenameBadSuffix = null;
+		static Boolean WaitOnCompletion = false;
+		static Boolean PrintMissing = false;
+		static Boolean PrintMismatch = false;
+		static UInt32 DirectoriesChecked = 0;
+		static UInt32 ListsChecked = 0;
+		static UInt32 FilesMissing = 0;
+		static UInt32 FilesBad = 0;
+		static UInt32 FilesGood = 0;
+		[STAThread]
+		static int Main(String[] args) {
+			String rootdirectory = null;
+			Console.Error.WriteLine("UCIS AutoCRCheck (c) 2014 Ivo Smits <Ivo@UCIS.nl>");
+			Console.Error.WriteLine("See http://wiki.ucis.nl/AutoCRCheck for more information");
+			for (int i = 0; i < args.Length; i++) {
+				if (args[i].StartsWith("-")) {
+					switch (args[i].Substring(1)) {
+						case "d":
+						case "delete":
+							DeleteBad = true;
+							break;
+						case "r":
+						case "rename":
+							RenameBadSuffix = args[++i];
+							break;
+						case "w":
+						case "wait":
+							WaitOnCompletion = true;
+							break;
+						case "printmissing":
+							PrintMissing = true;
+							break;
+						case "p":
+						case "printmismatch":
+							PrintMismatch = true;
+							break;
+						case "help":
+						case "h":
+							PrintCommandlineHelp(Console.Out);
+							return -1;
+						default:
+							Console.Error.WriteLine("Error: unknown command line argument: " + args[i]);
+							PrintCommandlineHelp(Console.Error);
+							return -1;
+					}
+				} else {
+					if (rootdirectory != null) {
+						Console.Error.WriteLine("Error: duplicate root directory specified.");
+						return -1;
+					}
+					rootdirectory = args[i];
+				}
+			}
+			if (rootdirectory == null) {
+				Console.Error.WriteLine("Root directory not set, waiting for GUI input...");
+				try {
+					using (new Control()) ;
+				} catch {
+					Console.Error.WriteLine("It looks like you're trying to run this application in a non-GUI session. Luckily we're handling this nearly fatal error for you.");
+					PrintCommandlineHelp(Console.Error);
+					return -1;
+				}
+				using (frmOptions options = new frmOptions()) {
+					DialogResult result = options.ShowDialog();
+					if (result != DialogResult.OK) return -2;
+					rootdirectory = options.RootDirectory;
+					DeleteBad = options.MismatchDelete;
+					RenameBadSuffix = options.MismatchRenameSuffix;
+					WaitOnCompletion = true;
+				}
+
+			}
+			if (!Directory.Exists(rootdirectory)) {
+				Console.Error.WriteLine("Error: root directory not found.");
+				return -1;
+			}
+			rootdirectory = Path.GetFullPath(rootdirectory);
+			ScanDirectory(rootdirectory);
+			String report = String.Format(
+				"{0} directories scanned.\n{1} .SFV files processed\n{2} files were missing\n{3} files had a mismatching checksum, they have been dealt with.\n{4} files are good",
+				DirectoriesChecked, ListsChecked, FilesMissing, FilesBad, FilesGood);
+			Console.Error.WriteLine(report);
+			Console.Error.WriteLine("Done.");
+			if (WaitOnCompletion) {
+				MessageBox.Show("All files have been checked." + Environment.NewLine + report, "UCIS AutoCRCheck", MessageBoxButtons.OK, MessageBoxIcon.Information);
+			}
+			return 0;
+		}
+		static void PrintCommandlineHelp(TextWriter w) {
+			w.WriteLine("UCIS AutoCRCheck recursively checks directories for .SFV files and handles mismatching checksums as instructed.");
+			w.WriteLine("Usage: AutoCRCheck.exe [options] [root directory]");
+			w.WriteLine("Possible options:");
+			w.WriteLine("    -delete            Delete mismatching files");
+			w.WriteLine("    -rename [suffix]   Rename mismatching files, append [suffix] to filename");
+			w.WriteLine("    -printmissing      Print full path of missing files");
+			w.WriteLine("    -printmismatch     Print full path of mismatched files");
+			w.WriteLine("    -wait              Wait for user input when done");
+			w.WriteLine("    -help              Display this message");
+			w.WriteLine();
+			w.WriteLine("Examples:");
+			w.WriteLine("    AutoCRCheck.exe . -rename .badcrc");
+			w.WriteLine("    AutoCRCheck.exe . -printmismatch > badfiles.txt");
+		}
+		static void ScanDirectory(String dir) {
+			DirectoriesChecked++;
+			Console.Error.WriteLine("Directory: {0}", dir);
+			foreach (String sfv in Directory.GetFiles(dir, "*.sfv")) {
+				ListsChecked++;
+				Console.Error.WriteLine("Checksum file: {0}", Path.GetFileName(sfv));
+				using (TextReader reader = File.OpenText(Path.Combine(dir, sfv))) {
+					while (true) {
+						String line = reader.ReadLine();
+						if (line == null) break;
+						if (line.Length == 0 || line[0] == ';') continue;
+						int lastspace = line.LastIndexOf(' ');
+						if (lastspace == -1) continue;
+						String file = line.Substring(0, lastspace).TrimEnd(' ');
+						String cksumstr = line.Substring(lastspace);
+						UInt32 goodcksum;
+						if (!UInt32.TryParse(cksumstr, NumberStyles.HexNumber, null, out goodcksum)) {
+							Console.Error.WriteLine("Failed to decode checksum string: {0}", cksumstr);
+							continue;
+						}
+						String filepath = Path.Combine(dir, file);
+						if (!File.Exists(filepath)) {
+							FilesMissing++;
+							Console.Error.WriteLine("File not found: {0}", file);
+							if (PrintMissing) Console.Out.WriteLine(filepath);
+							continue;
+						}
+						UInt32 realcksum;
+						Console.Error.Write("Checking file: {0}... ", file);
+						using (Stream input = File.OpenRead(filepath)) realcksum = CRCCalculate(input);
+						if (goodcksum != realcksum) {
+							FilesBad++;
+							Console.Error.WriteLine("Mismatch.");
+							if (PrintMismatch) Console.Out.WriteLine(filepath);
+							if (RenameBadSuffix != null) {
+								File.Move(filepath, filepath + RenameBadSuffix);
+							} else if (DeleteBad) {
+								File.Delete(filepath);
+							}
+						} else {
+							FilesGood++;
+							Console.Error.WriteLine("Good.");
+						}
+					}
+				}
+			}
+			foreach (String subdir in Directory.GetDirectories(dir)) {
+				ScanDirectory(Path.Combine(dir, subdir));
+			}
+		}
+		static readonly UInt32[] CRCTable = CRCGenerateTable();
+		static UInt32[] CRCGenerateTable() {
+			UInt32[] table = new UInt32[256];
+			for (UInt32 v = 0; v < 256; v++) {
+				UInt32 e = CRCReflect(v, 8) << 24;
+				for (int i = 0; i < 8; i++) {
+					if ((e & 0x80000000L) == 0) e <<= 1;
+					else e = (e << 1) ^ 0x04C11DB7;
+				}
+				table[v] = CRCReflect(e, 32);
+			}
+			return table;
+		}
+		static UInt32 CRCReflect(UInt32 r, int v) {
+			UInt32 ret = 0;
+			for (int i = 1; i < v + 1; i++, r >>= 1) if ((r & 1) != 0) ret |= 1u << (v - i);
+			return ret;
+		}
+		static uint CRCCalculate(Stream input) {
+			uint c = 0xffffffff;
+			Byte[] buffer = new Byte[Math.Min(1024, input.Length)];
+			while (true) {
+				int n = input.Read(buffer, 0, buffer.Length);
+				if (n <= 0) break;
+				for (int i = 0; i < n; i++) c = CRCTable[(c ^ buffer[i]) & 0xFF] ^ (c >> 8);
+			}
+			return c ^ 0xffffffff;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Properties/AssemblyInfo.cs	Fri Feb 07 23:23:08 2014 +0100
@@ -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("AutoCRCheck")]
+[assembly: AssemblyDescription("Automatic recursive .SFV file checker")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("UCIS Internet")]
+[assembly: AssemblyProduct("AutoCRCheck")]
+[assembly: AssemblyCopyright("Copyright © Ivo Smits 2014")]
+[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("512e59c7-986b-488f-b4b6-d9a78e7a5f17")]
+
+// 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")]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Properties/Resources.Designer.cs	Fri Feb 07 23:23:08 2014 +0100
@@ -0,0 +1,62 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:2.0.50727.5472
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace AutoCRCheck.Properties {
+
+
+	/// <summary>
+	///   A strongly-typed resource class, for looking up localized strings, etc.
+	/// </summary>
+	// 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", "2.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() {
+		}
+
+		/// <summary>
+		///   Returns the cached ResourceManager instance used by this class.
+		/// </summary>
+		[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+		internal static global::System.Resources.ResourceManager ResourceManager {
+			get {
+				if ((resourceMan == null)) {
+					global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AutoCRCheck.Properties.Resources", typeof(Resources).Assembly);
+					resourceMan = temp;
+				}
+				return resourceMan;
+			}
+		}
+
+		/// <summary>
+		///   Overrides the current thread's CurrentUICulture property for all
+		///   resource lookups using this strongly typed resource class.
+		/// </summary>
+		[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+		internal static global::System.Globalization.CultureInfo Culture {
+			get {
+				return resourceCulture;
+			}
+			set {
+				resourceCulture = value;
+			}
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Properties/Resources.resx	Fri Feb 07 23:23:08 2014 +0100
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Properties/Settings.Designer.cs	Fri Feb 07 23:23:08 2014 +0100
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:2.0.50727.5472
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace AutoCRCheck.Properties {
+
+
+	[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+	[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.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;
+			}
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Properties/Settings.settings	Fri Feb 07 23:23:08 2014 +0100
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
+  <Profiles>
+    <Profile Name="(Default)" />
+  </Profiles>
+  <Settings />
+</SettingsFile>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/frmOptions.Designer.cs	Fri Feb 07 23:23:08 2014 +0100
@@ -0,0 +1,185 @@
+namespace AutoCRCheck {
+	partial class frmOptions {
+		/// <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.fbdDirectoryBrowser = new System.Windows.Forms.FolderBrowserDialog();
+			this.label1 = new System.Windows.Forms.Label();
+			this.label2 = new System.Windows.Forms.Label();
+			this.txtRootDirectory = new System.Windows.Forms.TextBox();
+			this.btnRootDirectoryBrowse = new System.Windows.Forms.Button();
+			this.groupBox1 = new System.Windows.Forms.GroupBox();
+			this.radMismatchRename = new System.Windows.Forms.RadioButton();
+			this.radMismatchDelete = new System.Windows.Forms.RadioButton();
+			this.radMismatchNoAction = new System.Windows.Forms.RadioButton();
+			this.txtMismatchRenameSuffix = new System.Windows.Forms.TextBox();
+			this.btnStart = new System.Windows.Forms.Button();
+			this.groupBox1.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// label1
+			// 
+			this.label1.AutoSize = true;
+			this.label1.Location = new System.Drawing.Point(12, 65);
+			this.label1.Name = "label1";
+			this.label1.Size = new System.Drawing.Size(76, 13);
+			this.label1.TabIndex = 0;
+			this.label1.Text = "Root directory:";
+			// 
+			// label2
+			// 
+			this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+						| System.Windows.Forms.AnchorStyles.Right)));
+			this.label2.Location = new System.Drawing.Point(12, 9);
+			this.label2.Name = "label2";
+			this.label2.Size = new System.Drawing.Size(518, 50);
+			this.label2.TabIndex = 1;
+			this.label2.Text = "UCIS AutoCRCheck will recursively scan specified folder, looking for any .SFV fil" +
+				"es and checking the CRC checksums for the listed files. Mismatching files can be" +
+				" deleted or renamed.";
+			// 
+			// txtRootDirectory
+			// 
+			this.txtRootDirectory.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+						| System.Windows.Forms.AnchorStyles.Right)));
+			this.txtRootDirectory.Location = new System.Drawing.Point(94, 62);
+			this.txtRootDirectory.Name = "txtRootDirectory";
+			this.txtRootDirectory.Size = new System.Drawing.Size(396, 20);
+			this.txtRootDirectory.TabIndex = 2;
+			// 
+			// btnRootDirectoryBrowse
+			// 
+			this.btnRootDirectoryBrowse.Location = new System.Drawing.Point(496, 62);
+			this.btnRootDirectoryBrowse.Name = "btnRootDirectoryBrowse";
+			this.btnRootDirectoryBrowse.Size = new System.Drawing.Size(34, 20);
+			this.btnRootDirectoryBrowse.TabIndex = 3;
+			this.btnRootDirectoryBrowse.Text = "...";
+			this.btnRootDirectoryBrowse.UseVisualStyleBackColor = true;
+			this.btnRootDirectoryBrowse.Click += new System.EventHandler(this.btnRootDirectoryBrowse_Click);
+			// 
+			// groupBox1
+			// 
+			this.groupBox1.Controls.Add(this.radMismatchRename);
+			this.groupBox1.Controls.Add(this.radMismatchDelete);
+			this.groupBox1.Controls.Add(this.radMismatchNoAction);
+			this.groupBox1.Controls.Add(this.txtMismatchRenameSuffix);
+			this.groupBox1.Location = new System.Drawing.Point(15, 88);
+			this.groupBox1.Name = "groupBox1";
+			this.groupBox1.Size = new System.Drawing.Size(515, 90);
+			this.groupBox1.TabIndex = 4;
+			this.groupBox1.TabStop = false;
+			this.groupBox1.Text = "Mismatching files";
+			// 
+			// radMismatchRename
+			// 
+			this.radMismatchRename.AutoSize = true;
+			this.radMismatchRename.Location = new System.Drawing.Point(6, 65);
+			this.radMismatchRename.Name = "radMismatchRename";
+			this.radMismatchRename.Size = new System.Drawing.Size(153, 17);
+			this.radMismatchRename.TabIndex = 3;
+			this.radMismatchRename.Text = "Rename file, append suffix:";
+			this.radMismatchRename.UseVisualStyleBackColor = true;
+			this.radMismatchRename.CheckedChanged += new System.EventHandler(this.radMismatch_CheckedChanged);
+			// 
+			// radMismatchDelete
+			// 
+			this.radMismatchDelete.AutoSize = true;
+			this.radMismatchDelete.Location = new System.Drawing.Point(6, 42);
+			this.radMismatchDelete.Name = "radMismatchDelete";
+			this.radMismatchDelete.Size = new System.Drawing.Size(72, 17);
+			this.radMismatchDelete.TabIndex = 2;
+			this.radMismatchDelete.Text = "Delete file";
+			this.radMismatchDelete.UseVisualStyleBackColor = true;
+			this.radMismatchDelete.CheckedChanged += new System.EventHandler(this.radMismatch_CheckedChanged);
+			// 
+			// radMismatchNoAction
+			// 
+			this.radMismatchNoAction.AutoSize = true;
+			this.radMismatchNoAction.Checked = true;
+			this.radMismatchNoAction.Location = new System.Drawing.Point(6, 19);
+			this.radMismatchNoAction.Name = "radMismatchNoAction";
+			this.radMismatchNoAction.Size = new System.Drawing.Size(77, 17);
+			this.radMismatchNoAction.TabIndex = 1;
+			this.radMismatchNoAction.TabStop = true;
+			this.radMismatchNoAction.Text = "Do nothing";
+			this.radMismatchNoAction.UseVisualStyleBackColor = true;
+			this.radMismatchNoAction.CheckedChanged += new System.EventHandler(this.radMismatch_CheckedChanged);
+			// 
+			// txtMismatchRenameSuffix
+			// 
+			this.txtMismatchRenameSuffix.Enabled = false;
+			this.txtMismatchRenameSuffix.Location = new System.Drawing.Point(165, 64);
+			this.txtMismatchRenameSuffix.Name = "txtMismatchRenameSuffix";
+			this.txtMismatchRenameSuffix.Size = new System.Drawing.Size(100, 20);
+			this.txtMismatchRenameSuffix.TabIndex = 0;
+			this.txtMismatchRenameSuffix.Text = ".badcrc";
+			// 
+			// btnStart
+			// 
+			this.btnStart.Location = new System.Drawing.Point(455, 184);
+			this.btnStart.Name = "btnStart";
+			this.btnStart.Size = new System.Drawing.Size(75, 23);
+			this.btnStart.TabIndex = 5;
+			this.btnStart.Text = "Start";
+			this.btnStart.UseVisualStyleBackColor = true;
+			this.btnStart.Click += new System.EventHandler(this.btnStart_Click);
+			// 
+			// frmOptions
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.ClientSize = new System.Drawing.Size(542, 213);
+			this.Controls.Add(this.btnStart);
+			this.Controls.Add(this.groupBox1);
+			this.Controls.Add(this.btnRootDirectoryBrowse);
+			this.Controls.Add(this.txtRootDirectory);
+			this.Controls.Add(this.label2);
+			this.Controls.Add(this.label1);
+			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
+			this.MaximizeBox = false;
+			this.MinimizeBox = false;
+			this.Name = "frmOptions";
+			this.Text = "UCIS AutoCRCheck options";
+			this.Load += new System.EventHandler(this.Form1_Load);
+			this.groupBox1.ResumeLayout(false);
+			this.groupBox1.PerformLayout();
+			this.ResumeLayout(false);
+			this.PerformLayout();
+
+		}
+
+		#endregion
+
+		private System.Windows.Forms.FolderBrowserDialog fbdDirectoryBrowser;
+		private System.Windows.Forms.Label label1;
+		private System.Windows.Forms.Label label2;
+		private System.Windows.Forms.TextBox txtRootDirectory;
+		private System.Windows.Forms.Button btnRootDirectoryBrowse;
+		private System.Windows.Forms.GroupBox groupBox1;
+		private System.Windows.Forms.RadioButton radMismatchRename;
+		private System.Windows.Forms.RadioButton radMismatchDelete;
+		private System.Windows.Forms.RadioButton radMismatchNoAction;
+		private System.Windows.Forms.TextBox txtMismatchRenameSuffix;
+		private System.Windows.Forms.Button btnStart;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/frmOptions.cs	Fri Feb 07 23:23:08 2014 +0100
@@ -0,0 +1,37 @@
+using System;
+using System.IO;
+using System.Windows.Forms;
+
+namespace AutoCRCheck {
+	public partial class frmOptions : Form {
+		public frmOptions() {
+			InitializeComponent();
+		}
+
+		private void Form1_Load(object sender, EventArgs e) {
+			txtRootDirectory.Text = Environment.CurrentDirectory;
+		}
+
+		private void radMismatch_CheckedChanged(object sender, EventArgs e) {
+			txtMismatchRenameSuffix.Enabled = radMismatchRename.Checked;
+		}
+
+		private void btnStart_Click(object sender, EventArgs e) {
+			DialogResult = DialogResult.OK;
+			Close();
+		}
+
+		private void btnRootDirectoryBrowse_Click(object sender, EventArgs e) {
+			fbdDirectoryBrowser.Description = "Select root directory";
+			if (Directory.Exists(txtRootDirectory.Text)) fbdDirectoryBrowser.SelectedPath = txtRootDirectory.Text;
+			fbdDirectoryBrowser.ShowNewFolderButton = false;
+			if (fbdDirectoryBrowser.ShowDialog() == DialogResult.OK) {
+				txtRootDirectory.Text = fbdDirectoryBrowser.SelectedPath;
+			}
+		}
+
+		public String RootDirectory { get { return txtRootDirectory.Text; } }
+		public Boolean MismatchDelete { get { return radMismatchDelete.Checked; } }
+		public String MismatchRenameSuffix { get { return radMismatchRename.Checked ? txtMismatchRenameSuffix.Text : null; } }
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/frmOptions.resx	Fri Feb 07 23:23:08 2014 +0100
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="fbdDirectoryBrowser.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+</root>
\ No newline at end of file