/// <summary> /// Put the background worker to work /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void bgWorker_DoWork(object sender, DoWorkEventArgs e) { try { // We're off and running: resultStatus = ResultStatus.Running; // What we do depends on what mode we're in. In single-file mode, start hashing // the specified file: if (singleMode) { e.Result = HashEngine.HashFile(hashAlgorithm, files[0], bgWorker, e, outputType); } // Otherwise, start comparing the hashes of the files in the list: else { e.Result = HashEngine.CompareHashes(hashAlgorithm, files, bgWorker, e); } } catch (Exception ex) { MessageBox.Show(ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); resultStatus = ResultStatus.Error; e.Cancel = true; // Close is commented out here, because if this occurs, we'll be closing the dialog // from the background worker thread, not the GUI thread, and that throws an // exception. //Close(); } }
/// <summary> /// Perform the actual hash operation /// </summary> /// <param name="args">A <see cref="CmdLineAppArgs"/> object containing the parsed /// input parameters from the command line</param> /// <param name="overrideHash">If true, override the hash algorithm specified in /// args.Hash with the hash specified by hashToOverrideWith</param> /// <param name="hashToOverrideWith">If overrideHash is true, override the hash /// algorithm specified in args.Hash with this hash algorithm</param> /// <returns></returns> public static bool PerformHashes(CmdLineAppArgs args, bool overrideHash, Hashes hashToOverrideWith) { // If the arguments are null, return false to notify the caller that there's // nothing to do: if (args == null) { return(false); } // If we're being told to override the hash, check to make sure that the hash // specified in the arguments matches the hash we're supposed to override it // with. If they don't match, print a warning to the user and override the // hash. Otherwise, we'll let this quietly slip by. if (overrideHash && args.Hash != hashToOverrideWith) { Console.Error.WriteLine("WARNING: Can't override hash algorithm, " + GetHashSwitchString(args.Hash) + " switch ignored."); args.Hash = hashToOverrideWith; } // If the file list is empty and the input file parameter was not set, then // there's really not much for us to do. Complain and exit out with a false // result. if ((args.Files == null || args.Files.Length == 0) && String.IsNullOrEmpty(args.InputFile)) { Console.Error.WriteLine("ERROR: No file list or input file specified. Nothing to do!"); return(false); } // If the input file was specified but we also got a list of files on the // command line, we'll claim the input file overrides the list of files from // the arguments and null those out: if (!String.IsNullOrEmpty(args.InputFile) && args.Files != null && args.Files.Length > 0) { Console.Error.WriteLine("WARNING: Input file specified. File list on command line will be ignored."); args.Files = null; } // Now that it looks like we're going to do something, put on our asbestos // underpants: try { // If an input file was specified, try to read in its contents: if (!String.IsNullOrEmpty(args.InputFile)) { // Declare a list of strings to hold the intermediate values read // from the file: List <string> fileList = new List <string>(); // Now try to open up the file for reading: StreamReader reader = new StreamReader(args.InputFile); // Loop through the lines in the file and examine each one: string line = null; while ((line = reader.ReadLine()) != null) { // For the sake of data integrity, we'll ignore any empty lines // or lines that consist entirely of white space. As a convenience // to the user, we'll also allow they to put in comments by starting // a line with a hash/pound sign, which we'll also ignore. if (line.Length == 0 || Regex.IsMatch(line, @"^\s*$") || Regex.IsMatch(line, @"^#")) { continue; } // If we pass that test, add the contents of the line to the list. // Note that we'll strip any leading or trailing white space while // we're at it. fileList.Add(line.Trim()); } // Close the reader: reader.Close(); // If we got anything from the file, convert the list into a string // array and put that into the arguments: if (fileList.Count > 0) { args.Files = fileList.ToArray(); } } // We need to test again whether or not we have anything to do, because // reading the input file may have populated the file list where it was // empty before. If no files are listed, bail: if (args.Files == null || args.Files.Length == 0) { Console.Error.WriteLine("ERROR: No file list specified or input file contained nothing useful. Nothing to do!"); return(false); } // Now declare our output stream writer. If an output file was specified, // try to open that file, using the append flag as well. If no output file // was specified, the writer object will remain null, which will be our flag // below on where to send our output. StreamWriter writer = null; if (!String.IsNullOrEmpty(args.OutputFile)) { writer = new StreamWriter(args.OutputFile, args.AppendOutput); } // Now to get to work. First, we need to know what mode we're working in. // We'll handle compare mode first: if (args.CompareMode) { // Compare mode only makes sense if we've got more than one file to // compare. If not, we need to complain: if (args.Files.Length == 1) { Console.Error.WriteLine("ERROR: Cannot compare files unless two or more files are specified."); return(false); } // Print out the initial status message like above: ConsoleStatusUpdater status = null; if (writer == null) { status = new ConsoleStatusUpdater(); Console.WriteLine(); Console.Write("Comparing " + GetHashString(args.Hash) + " of " + args.Files.Length + " files... 0%"); } // Compute the hashes and compare the result. Note that the // displayed status might be less than 100% if the comparisons // fail. bool isMatch = HashEngine.CompareHashes(args.Hash, args.Files, status); // Print the result to the appropriate place: string result = null; if (isMatch) { result = "Congratulations! All " + args.Files.Length + " files match!"; } else { result = "WARNING! One or more of these " + args.Files.Length + " files do not match!"; } if (writer == null) { Console.WriteLine(); Console.WriteLine(result); } else { writer.WriteLine(result); } } // If we're not in compare mode, we must be hashing each file individually: else { // Loop through the file list: foreach (string file in args.Files) { // We've already warned the user if they tried to use a redirection // command, so ignore those here: if (IsRedirectionCommand(file)) { continue; } // Try to hash the file. Note that our actual result here is to // concatenate the result with the file name, giving us a similar // output to md5sum, shasum, and their friends. string result = HashEngine.HashFile(args.Hash, file, args.OutputType, null) + " " + file; // Write the result to the appropriate output: if (writer != null) { writer.WriteLine(result); } else { Console.WriteLine(result); } } } // Once we're finished, close the file if necessary: if (writer != null) { writer.Close(); } return(true); } // This needs to be prettied up, but for now just output the message from any // exception caught and return false to the caller to indicate an error: catch (Exception e) { Console.Error.WriteLine("ERROR: " + e.Message); return(false); } }