Esempio n. 1
0
        /// <summary>
        /// Report a warning
        /// </summary>
        /// <param name="message">Warning message</param>
        protected void OnWarningEvent(string message)
        {
            if (WarningEvent == null && WriteToConsoleIfNoListener && !SkipConsoleWriteIfNoWarningListener)
            {
                ConsoleMsgUtils.ShowWarning(message, EmptyLinesBeforeWarningMessages);
            }

            WarningEvent?.Invoke(message);
        }
Esempio n. 2
0
        /// <summary>
        /// Update the .lastused file for the given data file
        /// </summary>
        /// <param name="dataFile"></param>
        public static void UpdateLastUsedFile(FileInfo dataFile)
        {
            var lastUsedFilePath = dataFile.FullName + LASTUSED_FILE_EXTENSION;

            try
            {
                using (var writer = new StreamWriter(new FileStream(lastUsedFilePath, FileMode.Create, FileAccess.Write, FileShare.Read)))
                {
                    writer.WriteLine(DateTime.UtcNow.ToString(HashUtilities.DATE_TIME_FORMAT));
                }
            }
            catch (IOException)
            {
                // The file is likely open by another program; ignore this
            }
            catch (Exception ex)
            {
                ConsoleMsgUtils.ShowWarning(string.Format("Unable to create a new .LastUsed file at {0}: {1}", lastUsedFilePath, ex.Message));
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Looks for a .hashcheck file for the specified data file; returns false if not found
        /// If found, compares the stored values to the actual values (size, modification_date_utc, and hash)
        /// </summary>
        /// <param name="localFilePath">Data file to check</param>
        /// <param name="hashCheckFilePath">Hashcheck file for the given data file (auto-defined if blank)</param>
        /// <param name="errorMessage">Output: error message</param>
        /// <param name="checkDate">If True, compares UTC modification time; times must agree within 2 seconds</param>
        /// <param name="computeHash">If true, compute the file hash (every time); if false, only compare file size and date</param>
        /// <param name="checkSize">If true, compare the actual file size to that in the hashcheck file</param>
        /// <param name="assumedHashType">Hash type to assume if the .hashcheck file does not have a hashtype entry</param>
        /// <returns>True if the hashcheck file exists and the actual file matches the expected values; false if a mismatch, if .hashcheck is missing, or if a problem</returns>
        /// <remarks>The .hashcheck file has the same name as the data file, but with ".hashcheck" appended</remarks>
        // ReSharper disable once UnusedMember.Global
        public static bool ValidateFileVsHashcheck(
            string localFilePath, string hashCheckFilePath, out string errorMessage,
            bool checkDate = true, bool computeHash = true, bool checkSize = true,
            HashUtilities.HashTypeConstants assumedHashType = HashUtilities.HashTypeConstants.MD5)
        {
            errorMessage = string.Empty;

            try
            {
                var localFile = new FileInfo(localFilePath);
                if (!localFile.Exists)
                {
                    errorMessage = "File not found: " + localFile.FullName;
                    return(false);
                }

                var localHashcheckFile = new FileInfo(hashCheckFilePath);
                if (!localHashcheckFile.Exists)
                {
                    errorMessage = "Data file at " + localFile.FullName + " does not have a corresponding .hashcheck file named " + localHashcheckFile.Name;
                    return(false);
                }

                var expectedHashInfo = new HashUtilities.HashInfoType
                {
                    HashType = assumedHashType
                };

                var validFile = ValidateFileVsHashcheck(localFilePath, hashCheckFilePath, out errorMessage,
                                                        expectedHashInfo, checkDate, computeHash, checkSize, recheckIntervalDays: 0);
                return(validFile);
            }
            catch (Exception ex)
            {
                ConsoleMsgUtils.ShowWarning("Error in ValidateLocalFile: " + ex.Message);
                return(false);
            }
        }
        /// <summary>
        /// Parse the parameters and switches at the command line
        /// </summary>
        /// <param name="switchStartChar"></param>
        /// <param name="switchParameterChar"></param>
        /// <returns>Returns True if any command line parameters were found; otherwise false</returns>
        /// <remarks>
        /// If /? or /help is found, returns False and sets mShowHelp to True
        /// If there are no arguments at the commandline, returns false, but sets NoArgumentsProvided to true
        /// </remarks>
        public bool ParseCommandLine(char switchStartChar, char switchParameterChar)
        {
            mSwitches.Clear();
            mNonSwitchParameters.Clear();

            try
            {
                string commandLine;
                try
                {
                    // .CommandLine() returns the full command line
                    commandLine = Environment.CommandLine;

                    // .GetCommandLineArgs splits the command line at spaces, though it keeps text between double quotes together
                    // Note that .NET will strip out the starting and ending double quote if the user provides a parameter like this:
                    // MyProgram.exe "C:\Program Files\FileToProcess"
                    //
                    // In this case, paramList[1] will not have a double quote at the start but it will have a double quote at the end:
                    //  paramList[1] = C:\Program Files\FileToProcess"

                    // One very odd feature of Environment.GetCommandLineArgs() is that if the command line looks like this:
                    //    MyProgram.exe "D:\WorkDir\SubDir\" /O:D:\OutputDir
                    // Then paramList will have:
                    //    paramList[1] = D:\WorkDir\SubDir" /O:D:\OutputDir
                    //
                    // To avoid this problem instead specify the command line as:
                    //    MyProgram.exe "D:\WorkDir\SubDir" /O:D:\OutputDir
                    // which gives:
                    //    paramList[1] = D:\WorkDir\SubDir
                    //    paramList[2] = /O:D:\OutputDir
                    //
                    // Due to the idiosyncrasies of .GetCommandLineArgs, we will instead use SplitCommandLineParams to do the splitting
                    // paramList = Environment.GetCommandLineArgs()
                }
                catch (Exception ex)
                {
                    // In .NET 1.x, programs would fail if called from a network share
                    // This appears to be fixed in .NET 2.0 and above
                    // If an exception does occur here, we'll show the error message at the console, then sleep for 5 seconds

                    ConsoleMsgUtils.ShowWarning("------------------------------------------------------------------------------");
                    ConsoleMsgUtils.ShowWarning(ConsoleMsgUtils.WrapParagraph(
                                                    "This program cannot be run from a network share.  Please map a drive to the " +
                                                    "network share you are currently accessing or copy the program files and " +
                                                    "required DLLs to your local computer."));
                    ConsoleMsgUtils.ShowWarning("Exception: " + ex.Message);
                    ConsoleMsgUtils.ShowWarning("------------------------------------------------------------------------------");

                    PauseAtConsole();

                    NeedToShowHelp = true;
                    return(false);
                }

                if (DebugMode)
                {
                    Console.WriteLine();
                    Console.WriteLine("Debugging command line parsing");
                    Console.WriteLine();
                }

                var paramList = SplitCommandLineParams(commandLine);

                if (DebugMode)
                {
                    Console.WriteLine();
                }

                if (string.IsNullOrWhiteSpace(commandLine))
                {
                    if (DebugMode)
                    {
                        Console.WriteLine("Command line is empty (not even the Executable name is present)");
                    }
                    NoParameters = true;
                    return(false);
                }

                if (commandLine.IndexOf(switchStartChar + "?", StringComparison.Ordinal) > 0 ||
                    commandLine.ToLower().IndexOf(switchStartChar + "help", StringComparison.CurrentCultureIgnoreCase) > 0)
                {
                    NeedToShowHelp = true;
                    return(false);
                }

                if (paramList.Length == 1)
                {
                    if (DebugMode)
                    {
                        Console.WriteLine("No arguments were provided");
                    }

                    NoParameters = true;
                    return(false);
                }

                // Parse the command line
                // Note that paramList[0] is the path to the Executable for the calling program

                for (var paramIndex = 1; paramIndex <= paramList.Length - 1; paramIndex++)
                {
                    if (paramList[paramIndex].Length <= 0)
                    {
                        continue;
                    }

                    var paramName  = paramList[paramIndex].TrimStart(' ');
                    var paramValue = string.Empty;

                    bool isSwitchParam;
                    if (paramName.StartsWith(switchStartChar.ToString()))
                    {
                        isSwitchParam = true;
                    }
                    else if (paramName.StartsWith(ALTERNATE_SWITCH_CHAR.ToString()) || paramName.StartsWith(DEFAULT_SWITCH_CHAR.ToString()))
                    {
                        isSwitchParam = true;
                    }
                    else
                    {
                        // Parameter doesn't start with switchStartChar or / or -
                        isSwitchParam = false;
                    }

                    if (isSwitchParam)
                    {
                        // Look for switchParameterChar in paramList[paramIndex]
                        var charIndex = paramList[paramIndex].IndexOf(switchParameterChar);

                        if (charIndex >= 0)
                        {
                            // Parameter is of the form /I:MyParam or /I:"My Parameter" or -I:"My Parameter" or /MyParam:Setting
                            paramValue = paramName.Substring(charIndex + 1).Trim();

                            // Remove any starting and ending quotation marks
                            paramValue = paramValue.Trim('"');

                            paramName = paramName.Substring(0, charIndex);
                        }
                        else
                        {
                            // Parameter is of the form /S or -S
                        }

                        // Remove the switch character from paramName
                        paramName = paramName.Substring(1).Trim();

                        if (DebugMode)
                        {
                            Console.WriteLine("SwitchParam: " + paramName + "=" + paramValue);
                        }

                        // Note: This will add paramName if it doesn't exist (which is normally the case)
                        mSwitches[paramName] = paramValue;
                    }
                    else
                    {
                        // Non-switch parameter since switchParameterChar was not found and does not start with switchStartChar

                        // Remove any starting and ending quotation marks
                        paramName = paramName.Trim('"');

                        if (DebugMode)
                        {
                            Console.WriteLine("NonSwitchParam " + mNonSwitchParameters.Count + ": " + paramName);
                        }

                        mNonSwitchParameters.Add(paramName);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Error in ParseCommandLine", ex);
            }

            if (DebugMode)
            {
                Console.WriteLine();
                Console.WriteLine("Switch Count = " + mSwitches.Count);
                Console.WriteLine("NonSwitch Count = " + mNonSwitchParameters.Count);
                Console.WriteLine();
            }

            if (mSwitches.Count + mNonSwitchParameters.Count > 0)
            {
                return(true);
            }

            return(false);
        }
Esempio n. 5
0
        /// <summary>
        /// Validate that the hash value of a local file matches the expected hash info, creating the .hashcheck file if missing
        /// </summary>
        /// <param name="localFilePath">Local file path</param>
        /// <param name="hashCheckFilePath">Hashcheck file for the given data file (auto-defined if blank)</param>
        /// <param name="errorMessage">Output: error message</param>
        /// <param name="expectedHashInfo">Expected hash info (e.g. based on a remote file)</param>
        /// <param name="checkDate">If True, compares UTC modification time; times must agree within 2 seconds</param>
        /// <param name="computeHash">If true, compute the file hash every recheckIntervalDays (or every time if recheckIntervalDays is 0)</param>
        /// <param name="checkSize">If true, compare the actual file size to that in the hashcheck file</param>
        /// <param name="recheckIntervalDays">
        /// If the .hashcheck file is more than this number of days old, re-compute the hash value of the local file and compare to the hashcheck file
        /// Set to 0 to check the hash on every call to this method
        /// </param>
        /// <returns>True if the file is valid, otherwise false</returns>
        /// <remarks>
        /// Will create the .hashcheck file if missing
        /// Will also update the .lastused file for the local file
        /// </remarks>
        public static bool ValidateFileVsHashcheck(
            string localFilePath, string hashCheckFilePath,
            out string errorMessage,
            HashUtilities.HashInfoType expectedHashInfo,
            bool checkDate          = true, bool computeHash = true, bool checkSize = true,
            int recheckIntervalDays = 0)
        {
            try
            {
                var localFile = new FileInfo(localFilePath);
                if (!localFile.Exists)
                {
                    errorMessage = "File not found: " + localFilePath;
                    ConsoleMsgUtils.ShowWarning(errorMessage);
                    return(false);
                }

                FileInfo localHashcheckFile;
                if (string.IsNullOrWhiteSpace(hashCheckFilePath))
                {
                    localHashcheckFile = new FileInfo(localFile.FullName + HashUtilities.HASHCHECK_FILE_SUFFIX);
                }
                else
                {
                    localHashcheckFile = new FileInfo(hashCheckFilePath);
                }

                if (!localHashcheckFile.Exists)
                {
                    // Local .hashcheck file not found; create it
                    if (expectedHashInfo.HashType == HashUtilities.HashTypeConstants.Undefined)
                    {
                        expectedHashInfo.HashType = HashUtilities.HashTypeConstants.SHA1;
                    }

                    HashUtilities.CreateHashcheckFile(localFile.FullName, expectedHashInfo.HashType, out var localFileHash, out var warningMessage);

                    if (string.IsNullOrWhiteSpace(localFileHash))
                    {
                        if (string.IsNullOrWhiteSpace(warningMessage))
                        {
                            errorMessage = "Unable to compute the hash value for local file " + localFile.FullName;
                        }
                        else
                        {
                            errorMessage = warningMessage;
                        }

                        ConsoleMsgUtils.ShowWarning(errorMessage);
                        return(false);
                    }

                    if (!string.IsNullOrWhiteSpace(warningMessage))
                    {
                        ConsoleMsgUtils.ShowWarning(warningMessage);
                    }

                    // Compare the hash to expectedHashInfo.HashValue (if .HashValue is not "")
                    if (!string.IsNullOrWhiteSpace(expectedHashInfo.HashValue) && !localFileHash.Equals(expectedHashInfo.HashValue))
                    {
                        errorMessage = string.Format("Mismatch between the expected hash value and the actual hash value for {0}: {1} vs. {2}",
                                                     localFile.Name, expectedHashInfo.HashValue, localFileHash);
                        ConsoleMsgUtils.ShowWarning(errorMessage);
                        return(false);
                    }

                    // Create/update the .lastused file
                    UpdateLastUsedFile(localFile);

                    errorMessage = string.Empty;
                    return(true);
                }

                // Local .hashcheck file exists
                var localHashInfo = HashUtilities.ReadHashcheckFile(localHashcheckFile.FullName);

                if (expectedHashInfo.HashType != HashUtilities.HashTypeConstants.Undefined &&
                    !string.IsNullOrWhiteSpace(expectedHashInfo.HashValue) &&
                    !localHashInfo.HashValue.Equals(expectedHashInfo.HashValue))
                {
                    errorMessage = string.Format("Hash mismatch for {0}: expected {1} but actually {2}",
                                                 localFile.Name, expectedHashInfo.HashValue, localHashInfo.HashValue);
                    ConsoleMsgUtils.ShowWarning(errorMessage);
                    return(false);
                }

                if (checkSize && localFile.Length != localHashInfo.FileSize)
                {
                    errorMessage = string.Format("File size mismatch for {0}: expected {1:#,##0} bytes but actually {2:#,##0} bytes",
                                                 localFile.Name, localHashInfo.FileSize, localFile.Length);
                    ConsoleMsgUtils.ShowWarning(errorMessage);
                    return(false);
                }

                // Only compare dates if we are not comparing hash values
                if (!computeHash && checkDate)
                {
                    if (Math.Abs(localFile.LastWriteTimeUtc.Subtract(localHashInfo.FileDateUtc).TotalSeconds) > 2)
                    {
                        errorMessage = string.Format("File date mismatch for {0}: expected {1} UTC but actually {2} UTC",
                                                     localFile.Name,
                                                     localHashInfo.FileDateUtc.ToString(HashUtilities.DATE_TIME_FORMAT),
                                                     localFile.LastWriteTimeUtc.ToString(HashUtilities.DATE_TIME_FORMAT));
                        ConsoleMsgUtils.ShowWarning(errorMessage);
                        return(false);
                    }
                }

                if (computeHash)
                {
                    var lastCheckDays = DateTime.UtcNow.Subtract(localHashcheckFile.LastWriteTimeUtc).TotalDays;

                    if (recheckIntervalDays <= 0 || lastCheckDays > recheckIntervalDays)
                    {
                        // Compute the hash of the file
                        if (localHashInfo.HashType == HashUtilities.HashTypeConstants.Undefined)
                        {
                            errorMessage = "Hashtype is undefined; cannot compute the file hash to compare to the .hashcheck file";
                            ConsoleMsgUtils.ShowWarning(errorMessage);
                            return(false);
                        }

                        var actualHash = HashUtilities.ComputeFileHash(localFilePath, localHashInfo.HashType);

                        if (!actualHash.Equals(localHashInfo.HashValue))
                        {
                            errorMessage = "Hash mismatch: expecting " + localHashInfo.HashValue + " but computed " + actualHash;
                            ConsoleMsgUtils.ShowWarning(errorMessage);
                            return(false);
                        }
                    }
                }

                // Create/update the .lastused file
                UpdateLastUsedFile(localFile);

                errorMessage = string.Empty;
                return(true);
            }
            catch (Exception ex)
            {
                errorMessage = "Error validating " + localFilePath + " against the expected hash: " + ex.Message;
                ConsoleMsgUtils.ShowWarning(errorMessage);
                return(false);
            }
        }