private static bool SaveProject(string projectFilename, GeneratorOptions generatorOptions)
 {
     try
     {
         var fileInfo = new FileInfo(projectFilename);
         JsonSerializer <GeneratorOptions> ser = new JsonSerializer <GeneratorOptions>();
         if (!(Directory.Exists(fileInfo.DirectoryName)))
         {
             MessageBox.Show($@"Directory does not exist: {fileInfo.DirectoryName}", @"Oopsie!", MessageBoxButtons.OK,
                             MessageBoxIcon.Hand);
             return(true);
         }
         using (var fileStream = File.OpenWrite(projectFilename))
         {
             using (var streamWriter = new StreamWriter(fileStream))
             {
                 ser.SerializeToWriter(generatorOptions, streamWriter);
                 Settings.Default.OutputDirectory = new FileInfo(projectFilename).DirectoryName;
                 Settings.Default.ProjectFile     = projectFilename;
                 Settings.Default.Save();
             }
         }
         return(true);
     }
     catch (Exception e)
     {
         Console.WriteLine(e);
         return(false);
     }
 }
Example #2
0
        static void WriteMessagesToJson(IEnumerable <MessageModel> messages, TextWriter writer)
        {
            // OPT: if you are wondering why this code is handling the
            // serialization of JSON list manually instead of passing it as a
            // List<T> in a single method call to JsonSerializer.SerializeToWriter(dtoMessages)
            // then this is because it would mean that all messages from the
            // source message buffer would need to be read completely into
            // memory before serializing it into JSON and then writing the result
            // of that to the console or file. Instead this is a read one message
            // from the message buffer, copy it to a DTO object, serialize that
            // one message to JSON and then write that single JSON object to the
            // target which is a TextWriter.
            writer.Write("[");
            bool first = true;

            foreach (var message in messages)
            {
                if (first)
                {
                    first = false;
                }
                else
                {
                    writer.Write(",");
                }
                var dtoMessage = new MessageDtoModelV1(message);
                JsonSerializer.SerializeToWriter(dtoMessage, writer);
            }
            writer.WriteLine("]");
            writer.Flush();
        }
        private void abbreviationsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var dict = new Dictionary <string, string>();
            var ser  = new JsonSerializer <Dictionary <string, string> >();

            if (File.Exists("abbreviations.dict"))
            {
                try
                {
                    using (var streamReader = File.OpenText("abbreviations.dict"))
                    {
                        dict = ser.DeserializeFromReader(streamReader);
                    }
                }
                catch (Exception exception)
                {
                    Console.WriteLine(exception);
                }
            }

            var abbreviationsDictForm
                = new SimpleReflectionForm <Dictionary <string, string> >(dict ?? new Dictionary <string, string>(), true, "Abbreviations");
            var dialogResult = abbreviationsDictForm.ShowDialog(this);

            if (dialogResult != DialogResult.OK)
            {
                return;
            }
            dict = abbreviationsDictForm.Obj;
            using (var streamWriter = new StreamWriter("abbreviations.dict"))
            {
                ser.SerializeToWriter(dict, streamWriter);
            }
        }
Example #4
0
 private void SaveModel(string fileLocation)
 {
     using (var writer = new StreamWriter(fileLocation))
     {
         var serializer = new JsonSerializer<MusicModel>();
         serializer.SerializeToWriter(_musicViewModel.MusicModel, writer);
     }
 }
Example #5
0
        public static void Serialize(ErrorBatch entity, Stream requestStream)
        {
            var serializer = new JsonSerializer <ErrorBatch>();

            using (var textWriter = new StreamWriter(requestStream))
            {
                serializer.SerializeToWriter(entity, textWriter);
            }
        }
Example #6
0
        void SerializeChunk(List <MessageDtoModelV1> chunk, TextWriter writer)
        {
            DateTime start, stop;

            start = DateTime.UtcNow;
            JsonSerializer.SerializeToWriter(chunk, writer);
            stop = DateTime.UtcNow;
#if LOG4NET && MSGBUF_DEBUG
            f_Logger.DebugFormat("SerializeChunk(): {0} items took: {1:0.00} ms",
                                 chunk.Count,
                                 (stop - start).TotalMilliseconds);
#endif
        }
Example #7
0
        public override void Add(MessageModel msg)
        {
            if (msg == null)
            {
                throw new ArgumentNullException("msg");
            }

            /*
             * if (MaxCapacity > 0 && Index.Count >= MaxCapacity) {
             *  RemoveAt(0);
             * }
             */

            var msgFileName = String.Format("{0}.v1.json", MessageNumber++);
            var msgFilePath = Path.Combine(RepositoryPath, msgFileName);

            using (var writer = File.OpenWrite(msgFilePath))
                using (var textWriter = new StreamWriter(writer, Encoding.UTF8)) {
                    JsonSerializer.SerializeToWriter(msg, textWriter);
                }

            DateTime start, stop;

            lock (Repository) {
                start = DateTime.UtcNow;
                var index = Repository.Index;
                //index.Stage(msgFilePath);
                // OPT: Stage() writes the index to disk on each call
                index.AddToIndex(msgFileName);
                stop = DateTime.UtcNow;
            }
#if LOG4NET && MSGBUF_DEBUG
            f_Logger.DebugFormat("Add(): Index.AddToIndex() took: {0:0.00} ms",
                                 (stop - start).TotalMilliseconds);
#endif

            // FIXME: delete file when index was written to disk
            File.Delete(msgFilePath);

            lock (CommitMessage) {
                CommitMessage.Append(
                    String.Format("{0}: {1}\n", msgFileName, msg.ToString())
                    );
            }

            // TODO: create tree, commit tree, repack repo reguraly (see rugged docs)
        }
        public Task WriteAsync(OutputFormatterWriteContext context)
        {
            var response = context.HttpContext.Response;

            response.ContentType = "application/json";

            if (context.Object == null)
            {
                response.Body.WriteByte(192);
                return(Task.CompletedTask);
            }

            using (var writer = context.WriterFactory(response.Body, Encoding.UTF8))
            {
                JsonSerializer.SerializeToWriter(context.Object, writer);
                return(Task.CompletedTask);
            }
        }
Example #9
0
        public void Does_escape_string_when_serializing_to_TextWriter()
        {
            var expected = @"String with backslashes '\', 'single' and ""double quotes"", (along		with	other	special	symbols	like	tabs) wich may broke incorrect serializing/deserializing implementation ;)";

            var json = "\"String with backslashes '\\\\', 'single' and \\\"double quotes\\\", (along\\t\\twith\\tother\\tspecial\\tsymbols\\tlike\\ttabs) wich may broke incorrect serializing/deserializing implementation ;)\"";

            using (var ms = new MemoryStream())
            {
                var sw = new StreamWriter(ms);
                JsonSerializer.SerializeToWriter(expected, sw);
                sw.Flush();

                using (var sr = new StreamReader(ms))
                {
                    ms.Position = 0;
                    var ssJson = sr.ReadToEnd();
                    Assert.That(ssJson, Is.EqualTo(json));

                    ms.Position = 0;
                    var ssString = JsonSerializer.DeserializeFromReader(sr, typeof(string));
                    Assert.That(ssString, Is.EqualTo(expected));
                }
            }
        }
Example #10
0
 private void WriteTo(TextWriter writer, T value)
 {
     _serializer.SerializeToWriter(value, writer);
     writer.WriteLine();
     writer.Flush();
 }
        public void ServiceStackSerialize()
        {
            DatabaseCompat db = GetNorthwindObject();
            JsonSerializer<DatabaseCompat> serializer = new JsonSerializer<DatabaseCompat>();
            serializer.SerializeToWriter(db, TextWriter.Null);

            Time(Iterations, () => serializer.SerializeToWriter(db, TextWriter.Null));
        }
Example #12
0
        private static void Main(string[] args)
        {
            //TODO Live Registry support

            var dumpWarning = false;

            var nlogPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "nlog.config");

            if (File.Exists(nlogPath) == false)
            {
                var config = new LoggingConfiguration();
                var loglevel = LogLevel.Info;

                var layout = @"${message}";

                var consoleTarget = new ColoredConsoleTarget();

                config.AddTarget("console", consoleTarget);

                consoleTarget.Layout = layout;

                var rule1 = new LoggingRule("*", loglevel, consoleTarget);
                config.LoggingRules.Add(rule1);

                LogManager.Configuration = config;
                dumpWarning = true;
            }

            _logger = LogManager.GetCurrentClassLogger();

            if (dumpWarning)
            {
                _logger.Warn("Nlog.config missing! Using default values...");
            }

            if (!CheckForDotnet46())
            {
                _logger.Warn(".net 4.6 not detected. Please install .net 4.6 and try again.");
                return;
            }

            var p = new FluentCommandLineParser<ApplicationArguments>
            {
                IsCaseSensitive = false
            };

//            p.Setup(arg => arg.HiveFile)
//                .As("Hive")
//                .WithDescription("\tHive to search. --Hive or --Dir is required.");

            p.Setup(arg => arg.Directory)
                .As("Dir")
                .WithDescription("\tDirectory to look for hives (recursively)");

//            p.Setup(arg => arg.Literal)
//                .As("Literal")
//                .WithDescription("\tIf present, --sd and --ss search value will not be interpreted as ASCII or Unicode byte strings");

//            p.Setup(arg => arg.RecoverDeleted)
//                .As("Recover")
//                .WithDescription("\tIf present, recover deleted keys/values");

//            p.Setup(arg => arg.DumpKey)
//                .As("DumpKey")
//                .WithDescription("\tDump given key (and all subkeys) and values as json");

//            p.Setup(arg => arg.DumpDir)
//                .As("DumpDir")
//                .WithDescription("\tDirectory to save json output");

//            p.Setup(arg => arg.Recursive)
//                .As("Recursive")
//                .WithDescription("Dump keys/values recursively (ignored if --ValueName used). This option provides FULL details about keys and values");

//            p.Setup(arg => arg.RegEx)
//                .As("RegEx")
//                .WithDescription("\tIf present, treat <string> in --sk, --sv, --sd, and --ss as a regular expression")
//                .SetDefault(false);

//            p.Setup(arg => arg.Sort)
//                .As("Sort")
//                .WithDescription("\tIf present, sort the output").SetDefault(false);

//            p.Setup(arg => arg.SuppressData)
//                .As("SuppressData")
//                .WithDescription("If present, do not show data when using --sd or --ss\r\n").SetDefault(false);

//            p.Setup(arg => arg.KeyName)
//                .As("KeyName")
//                .WithDescription("\tKey name. All values under this key will be dumped");

            // added option by CDI -- begin
            p.Setup(arg => arg.SaveTo)
                .As("SaveTo")
                .WithDescription("\tParsed data will be written to AutoRunParser_Output.csv in this directory");

            p.Setup(arg => arg.NoHeader)
                .As("NoHeader")
                .WithDescription("\tOutput to CSV without header");
            // added option by CDI -- end

//            p.Setup(arg => arg.ValueName)
//                .As("ValueName")
//                .WithDescription("Value name. Only this value will be dumped");

//            p.Setup(arg => arg.SaveToName)
//                .As("SaveToName")
//                .WithDescription("Saves ValueName value data in binary form to file\r\n");

//            p.Setup(arg => arg.StartDate)
//                .As("StartDate")
//                .WithDescription("Start date to look for last write timestamps (UTC). If EndDate is not supplied, last writes AFTER this date will be returned");

//            p.Setup(arg => arg.EndDate)
//                .As("EndDate")
//                .WithDescription("\tEnd date to look for last write timestamps (UTC). If StartDate is not supplied, last writes BEFORE this date will be returned");

//            p.Setup(arg => arg.MinimumSize)
//                .As("MinSize")
//                .WithDescription("\tFind values with data size >= MinSize (specified in bytes)");

//            p.Setup(arg => arg.SimpleSearchKey)
//                .As("sk")
//                .WithDescription("\tSearch for <string> in key names.");

//            p.Setup(arg => arg.SimpleSearchValue)
//                .As("sv")
//                .WithDescription("\tSearch for <string> in value names");

//            p.Setup(arg => arg.SimpleSearchValueData)
//                .As("sd")
//                .WithDescription("\tSearch for <string> in value record's value data");

//            p.Setup(arg => arg.SimpleSearchValueSlack)
//                .As("ss")
//                .WithDescription("\tSearch for <string> in value record's value slack");

            var header =
                $"AutoRunParser version {Assembly.GetExecutingAssembly().GetName().Version}" +
                $" modified by CDI, Inc." +
                "\r\n(Original Author: Eric Zimmerman)" +
                "\r\n\r\nNote: Enclose all strings containing spaces (and all RegEx) with double quotes";

            var footer = @"Example: AutoRunParser.exe --Dir C:\data\ --SaveTo C:\output\";

//            var footer = @"Example: RECmd.exe --Hive ""C:\Temp\UsrClass 1.dat"" --sk URL --Recover" + "\r\n\t " +
//                         @"RECmd.exe --Hive ""D:\temp\UsrClass 1.dat"" --StartDate ""11/13/2014 15:35:01"" " + "\r\n\t " +
//                         @"RECmd.exe --Hive ""D:\temp\UsrClass 1.dat"" --RegEx --sv ""(App|Display)Name"" " + "\r\n\t " +
//                         @"RECmd.exe --Hive ""D:\temp\UsrClass 1.dat"" --StartDate ""05/20/2014 19:00:00"" --EndDate ""05/20/2014 23:59:59"" " + "\r\n\t " +
//                         @"RECmd.exe --Hive ""D:\temp\UsrClass 1.dat"" --StartDate ""05/20/2014 07:00:00 AM"" --EndDate ""05/20/2014 07:59:59 PM"" ";

            p.SetupHelp("?", "help").WithHeader(header).Callback(text => _logger.Info(text + "\r\n" + footer));

            var result = p.Parse(args);

            if (result.HelpCalled)
            {
                return;
            }

            if (result.HasErrors)
            {
                _logger.Error("");
                _logger.Error(result.ErrorText);

                if (result.ErrorText.Contains("--dir"))
                {
                    _logger.Error("Remove the trailing backslash from the --dir argument and try again");
                }              
 
                p.HelpOption.ShowHelp(p.Options);

                return;
            }

            var hivesToProcess = new List<string>();
            var systemHives = new List<string>();
            var softwareHives = new List<string>();
            var ntuserHives = new List<string>();

            if (p.Object.HiveFile?.Length > 0)
            {
                hivesToProcess.Add(p.Object.HiveFile);
            }
            else if (p.Object.Directory?.Length > 0)
            {
                if (Directory.Exists(p.Object.Directory) == false)
                {
                    _logger.Error($"Directory '{p.Object.Directory}' does not exist.");
                    return;
                }

//                var files = Directory.GetFiles(p.Object.Directory, "*", SearchOption.AllDirectories);

                foreach (string fileName in Directory.GetFiles(p.Object.Directory, "*", SearchOption.AllDirectories))
                {
                    Stream st = File.OpenRead(fileName);
                    if (st.Length < 4)
                        continue;

                    BinaryReader br = new BinaryReader(st);
                    if (br.ReadInt32() != 1718052210) // means not "regf"
                        continue;

                    if (Path.GetFileName(fileName).ToUpper().Contains("SYSTEM"))
                    {
                        systemHives.Add(fileName);
                        hivesToProcess.Add(fileName);
                    }
                    else if (Path.GetFileName(fileName).ToUpper().Contains("SOFTWARE"))
                    {
                        softwareHives.Add(fileName);
                        hivesToProcess.Add(fileName);
                    }
                    else if (Path.GetFileName(fileName).ToUpper().Contains("NTUSER.DAT"))
                    {
                        ntuserHives.Add(fileName);
                        hivesToProcess.Add(fileName);
                    }
                }
            }
            else
            {
                p.HelpOption.ShowHelp(p.Options);
                return;
            }

            _logger.Info(header);
            _logger.Info("");

            if (hivesToProcess.Count == 0)
            {
                _logger.Warn("No hives were found. Exiting...");

                return;
            }

            // added by CDI for automation
            if (p.Object.Directory.Length > 0 && p.Object.SaveTo.Length > 0)
            {
                if (Directory.Exists(p.Object.SaveTo) == false)
                {
                    try
                    {
                        Directory.CreateDirectory(p.Object.SaveTo);
                    }
                    catch (Exception ex)
                    {
                        _logger.Error($"Error creating SaveTo '{p.Object.SaveTo}': {ex.Message}. Exiting");
                        return;
                    }
                }

                var outFileBase = string.Empty;
                outFileBase = $"AutoRunParser_Output.csv";
                var outFileName = Path.Combine(p.Object.SaveTo, outFileBase);

                var sw = new StreamWriter(outFileName, true, System.Text.Encoding.Unicode);
                sw.AutoFlush = true;
                sw.WriteLine("FilePath\tKey\tName\tValue\tLastWrittenTimeLocal\tLastWrittenTimeUTC");

                foreach (var systemHive in systemHives)
                {

                    var reg = new RegistryHive(systemHive)
                    {
                        RecoverDeleted = p.Object.RecoverDeleted
                    };

                    reg.ParseHive();
//                    var hive = new RegistryHiveOnDemand(systemHive);
                    var subKey = reg.GetKey("Select");
                    if (subKey == null)
                    {
                        _logger.Warn($"no SYSTEM hive: {systemHive}");
                        continue;
                    }
                    var currentCtlSet = int.Parse(subKey.Values.Single(c => c.ValueName == "Current").ValueData);

                    StreamReader cReader = new StreamReader(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + @"\system.txt", System.Text.Encoding.Default);

                    // 1行ごとに処理
                    while (cReader.Peek() >= 0)
                    {
                        string keyName = cReader.ReadLine();
                        var key = reg.GetKey($@"ControlSet00{currentCtlSet}\{keyName}");

                        if (key == null)
                        {
                            _logger.Warn($"Key not found: {keyName}");
                            continue;
                        }
                        WriteSpecificKeyInfo(key, sw, systemHive);
                    }
                    cReader.Close();
                }

                foreach (var softwareHive in softwareHives)
                {
                    var reg = new RegistryHive(softwareHive)
                    {
                        RecoverDeleted = p.Object.RecoverDeleted
                    };
                    reg.ParseHive();

                    StreamReader cReader = new StreamReader(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + @"\software.txt", System.Text.Encoding.Default);

                    // 1行ごとに処理
                    while (cReader.Peek() >= 0)
                    {
                        string keyName = cReader.ReadLine();
                        var key = reg.GetKey(keyName);

                        if (key == null)
                        {
                            _logger.Warn($"Key not found: {keyName}");
                            continue;
                        }
                        WriteSpecificKeyInfo(key, sw, softwareHive);
                    }
                    cReader.Close();

                }

                foreach (var ntuserHive in ntuserHives)
                {
                    var reg = new RegistryHive(ntuserHive)
                    {
                        RecoverDeleted = p.Object.RecoverDeleted
                    };
                    reg.ParseHive();

                    StreamReader cReader = new StreamReader(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + @"\ntuser.txt", System.Text.Encoding.Default);

                    // 1行ごとに処理
                    while (cReader.Peek() >= 0)
                    {
                        string keyName = cReader.ReadLine();
                        var key = reg.GetKey(keyName);

                        if (key == null)
                        {
                            _logger.Warn($"Key not found: {keyName}");
                            continue;
                        }
                        WriteSpecificKeyInfo(key, sw, ntuserHive);
                    }
                    cReader.Close();

                }

                _logger.Warn($"Saved to '{outFileName}'");
                sw.Close();
                return;
            }

            var totalHits = 0;
            var hivesWithHits = 0;
            double totalSeconds = 0;

            foreach (var hiveToProcess in hivesToProcess)
            {

                _logger.Info("");
                _logger.Info($"Processing hive '{hiveToProcess}'");
                _logger.Info("");

                if (File.Exists(hiveToProcess) == false)
                {
                    _logger.Warn($"'{hiveToProcess}' does not exist. Skipping");
                    continue;
                }

                try
                {
                    var reg = new RegistryHive(hiveToProcess)
                    {
                        RecoverDeleted = p.Object.RecoverDeleted
                    };

                    _sw = new Stopwatch();
                    _sw.Start();

                    reg.ParseHive();

                    _logger.Info("");

                    if (p.Object.DumpKey.Length > 0 && p.Object.DumpDir.Length > 0)
                    {
                        if (Directory.Exists(p.Object.DumpDir) == false)
                        {
                            try
                            {
                                Directory.CreateDirectory(p.Object.DumpDir);
                            }
                            catch (Exception ex)
                            {
                                _logger.Error($"Error creating DumpDir '{p.Object.DumpDir}': {ex.Message}. Exiting");
                                return;
                            }
                        }

                        var key = reg.GetKey(p.Object.DumpKey);

                        if (key == null)
                        {
                            _logger.Warn($"Key not found: {p.Object.DumpKey}. Exiting");
                            return;
                        }
                        
                        var nout = $"{key.KeyName}_dump.json";
                        var fout = Path.Combine(p.Object.DumpDir, nout);

                        _logger.Info("Found key. Dumping data. Be patient as this can take a while...");

                        var jsons = new JsonSerializer<RegistryKey>();

                        //TODO need a way to get a simple representation of things here, like
                        //name, path, date, etc vs EVERYTHING
                        

                        using (var sw = new StreamWriter(fout))
                        {
                            sw.AutoFlush = true;
                            jsons.SerializeToWriter(key,sw);
                        }
                                              
                        _logger.Warn($"'{p.Object.DumpKey}' saved to '{fout}'");

                    }
                    else if (p.Object.KeyName.Length > 0)
                    {
                        var key = reg.GetKey(p.Object.KeyName);

                        if (key == null)
                        {
                            _logger.Warn($"Key '{p.Object.KeyName}' not found.");
                            DumpStopWatchInfo();
                            continue;
                        }

                        if (p.Object.ValueName.Length > 0)
                        {
                            var val = key.Values.SingleOrDefault(c => c.ValueName == p.Object.ValueName);

                            if (val == null)
                            {
                                _logger.Warn($"Value '{p.Object.ValueName}' not found for key '{p.Object.KeyName}'.");

                                DumpStopWatchInfo();
                                continue;
                            }

                            _sw.Stop();
                            totalSeconds += _sw.Elapsed.TotalSeconds;

                            _logger.Info(val);

                            hivesWithHits += 1;
                            totalHits += 1;

                            if (p.Object.SaveToName.Length > 0)
                            {
                                var baseDir = Path.GetDirectoryName(p.Object.SaveToName);
                                if (Directory.Exists(baseDir) == false)
                                {
                                    Directory.CreateDirectory(baseDir);
                                }

                                _logger.Info($"Saving contents of '{val.ValueName}' to '{p.Object.SaveToName}'");
                                File.WriteAllBytes(p.Object.SaveToName, val.ValueDataRaw);
                            }

                            DumpStopWatchInfo();

                            continue;
                        }

                        hivesWithHits += 1;
                        totalHits += 1;

                        _sw.Stop();
                        totalSeconds += _sw.Elapsed.TotalSeconds;

                        DumpRootKeyName(reg);

                        DumpKey(key, p.Object.Recursive);

                        DumpStopWatchInfo();
                    }
                    else if (p.Object.MinimumSize > 0)
                    {
                        var hits = reg.FindByValueSize(p.Object.MinimumSize).ToList();
                        _sw.Stop();
                        totalSeconds += _sw.Elapsed.TotalSeconds;

                        if (p.Object.Sort)
                        {
                            hits = hits.OrderBy(t => t.Value.ValueDataRaw.Length).ToList();
                        }

                        DumpRootKeyName(reg);

                        hivesWithHits += 1;
                        totalHits += hits.Count;

                        foreach (var valueBySizeInfo in hits)
                        {
                            _logger.Info(
                                $"Key: {Helpers.StripRootKeyNameFromKeyPath(valueBySizeInfo.Key.KeyPath)}, Value: {valueBySizeInfo.Value.ValueName}, Size: {valueBySizeInfo.Value.ValueDataRaw.Length:N0}");
                        }

                        _logger.Info("");

                        var plural = "s";
                        if (hits.Count() == 1)
                        {
                            plural = "";
                        }
                        _logger.Info(
                            $"Found {hits.Count():N0} value{plural} with size greater or equal to {p.Object.MinimumSize:N0} bytes");
                        DumpStopWatchInfo();
                    }
                    else if (p.Object.StartDate != null || p.Object.EndDate != null)
                    {
                        DateTimeOffset start;
                        DateTimeOffset end;
                        var startOk = DateTimeOffset.TryParse(p.Object.StartDate + "-0", out start);
                        var endOk = DateTimeOffset.TryParse(p.Object.EndDate + "-0", out end);

                        DateTimeOffset? startGood = null;
                        DateTimeOffset? endGood = null;
                        var hits = new List<SearchHit>();

                        if (!startOk && p.Object.StartDate != null)
                        {
                            throw new InvalidCastException("'StartDate' is not a valid datetime value");
                        }
                        if (!endOk && p.Object.EndDate != null)
                        {
                            throw new InvalidCastException("'EndDate' is not a valid datetime value");
                        }

                        if (startOk && endOk)
                        {
                            startGood = start;
                            endGood = end;
                            hits = reg.FindByLastWriteTime(startGood, endGood).ToList();
                        }
                        else if (startOk)
                        {
                            startGood = start;

                            hits = reg.FindByLastWriteTime(startGood, null).ToList();
                        }
                        else if (endOk)
                        {
                            endGood = end;
                            hits = reg.FindByLastWriteTime(null, endGood).ToList();
                        }

                        _sw.Stop();
                        totalSeconds += _sw.Elapsed.TotalSeconds;

                        if (p.Object.Sort)
                        {
                            hits = hits.OrderBy(t => t.Key.LastWriteTime ?? new DateTimeOffset()).ToList();
                        }

                        DumpRootKeyName(reg);

                        hivesWithHits += 1;
                        totalHits += hits.Count;

                        foreach (var searchHit in hits)
                        {
                            searchHit.StripRootKeyName = true;
                            _logger.Info($"Last write: {searchHit.Key.LastWriteTime}  Key: {searchHit}");
                        }

                        var suffix = string.Empty;

                        if (startGood != null || endGood != null)
                        {
                            suffix = $"between {startGood} and {endGood}";
                        }
                        if (startGood != null && endGood == null)
                        {
                            suffix = $"after {startGood}";
                        }
                        else if (endGood != null && startGood == null)
                        {
                            suffix = $"before {endGood}";
                        }

                        _logger.Info("");

                        var plural = "s";
                        if (hits.Count() == 1)
                        {
                            plural = "";
                        }
                        _logger.Info($"Found {hits.Count():N0} key{plural} with last write {suffix}");

                        DumpStopWatchInfo();
                    }
                    else if (p.Object.SimpleSearchKey.Length > 0 || p.Object.SimpleSearchValue.Length > 0 ||
                             p.Object.SimpleSearchValueData.Length > 0 || p.Object.SimpleSearchValueSlack.Length > 0)
                    {
                        List<SearchHit> hits = null;

                        if (p.Object.SimpleSearchKey.Length > 0)
                        {
                            hits = reg.FindInKeyName(p.Object.SimpleSearchKey, p.Object.RegEx).ToList();
                            if (p.Object.Sort)
                            {
                                hits = hits.OrderBy(t => t.Key.KeyName).ToList();
                            }
                        }
                        else if (p.Object.SimpleSearchValue.Length > 0)
                        {
                            hits = reg.FindInValueName(p.Object.SimpleSearchValue, p.Object.RegEx).ToList();
                            if (p.Object.Sort)
                            {
                                hits = hits.OrderBy(t => t.Value.ValueName).ToList();
                            }
                        }
                        else if (p.Object.SimpleSearchValueData.Length > 0)
                        {
                            hits =
                                reg.FindInValueData(p.Object.SimpleSearchValueData, p.Object.RegEx, p.Object.Literal)
                                    .ToList();
                            if (p.Object.Sort)
                            {
                                hits = hits.OrderBy(t => t.Value.ValueData).ToList();
                            }
                        }
                        else if (p.Object.SimpleSearchValueSlack.Length > 0)
                        {
                            hits =
                                reg.FindInValueDataSlack(p.Object.SimpleSearchValueSlack, p.Object.RegEx,
                                    p.Object.Literal)
                                    .ToList();
                            if (p.Object.Sort)
                            {
                                hits = hits.OrderBy(t => t.Value.ValueData).ToList();
                            }
                        }

                        if (hits == null)
                        {
                            _logger.Warn("No search results found");
                            DumpStopWatchInfo();
                            continue;
                        }

                        _sw.Stop();
                        totalSeconds += _sw.Elapsed.TotalSeconds;

                        DumpRootKeyName(reg);

                        //set up highlighting
                        var words = new HashSet<string>();
                        foreach (var searchHit in hits)
                        {
                            if (p.Object.SimpleSearchKey.Length > 0)
                            {
                                words.Add(p.Object.SimpleSearchKey);
                            }
                            else if (p.Object.SimpleSearchValue.Length > 0)
                            {
                                words.Add(p.Object.SimpleSearchValue);
                            }
                            else if (p.Object.SimpleSearchValueData.Length > 0)
                            {
                                if (p.Object.RegEx)
                                {
                                    words.Add(p.Object.SimpleSearchValueData);
                                }
                                else
                                {
                                    words.Add(searchHit.HitString);
                                }
                            }
                            else if (p.Object.SimpleSearchValueSlack.Length > 0)
                            {
                                if (p.Object.RegEx)
                                {
                                    words.Add(p.Object.SimpleSearchValueSlack);
                                }
                                else
                                {
                                    words.Add(searchHit.HitString);
                                }
                            }
                        }

                        AddHighlightingRules(words.ToList(), p.Object.RegEx);

                        hivesWithHits += 1;
                        totalHits += hits.Count;

                        foreach (var searchHit in hits)
                        {
                            searchHit.StripRootKeyName = true;

                            if (p.Object.SimpleSearchValueData.Length > 0 || p.Object.SimpleSearchValueSlack.Length > 0)
                            {
                                if (p.Object.SuppressData)
                                {
                                    _logger.Info(
                                        $"Key: {Helpers.StripRootKeyNameFromKeyPath(searchHit.Key.KeyPath)}, Value: {searchHit.Value.ValueName}");
                                }
                                else
                                {
                                    if (p.Object.SimpleSearchValueSlack.Length > 0)
                                    {
                                        _logger.Info(
                                            $"Key: {Helpers.StripRootKeyNameFromKeyPath(searchHit.Key.KeyPath)}, Value: {searchHit.Value.ValueName}, Slack: {searchHit.Value.ValueSlack}");
                                    }
                                    else
                                    {
                                        _logger.Info(
                                            $"Key: {Helpers.StripRootKeyNameFromKeyPath(searchHit.Key.KeyPath)}, Value: {searchHit.Value.ValueName}, Data: {searchHit.Value.ValueData}");
                                    }
                                }
                            }
                            else if (p.Object.SimpleSearchKey.Length > 0)
                            {
                                _logger.Info($"Key: {Helpers.StripRootKeyNameFromKeyPath(searchHit.Key.KeyPath)}");
                            }
                            else if (p.Object.SimpleSearchValue.Length > 0)
                            {
                                _logger.Info(
                                    $"Key: {Helpers.StripRootKeyNameFromKeyPath(searchHit.Key.KeyPath)}, Value: {searchHit.Value.ValueName}");
                            }
                        }

                        var target = (ColoredConsoleTarget) LogManager.Configuration.FindTargetByName("console");
                        target.WordHighlightingRules.Clear();

                        var suffix = string.Empty;
                        var withRegex = string.Empty;

                        var plural = "s";
                        if (hits.Count() == 1)
                        {
                            plural = "";
                        }

                        if (p.Object.SimpleSearchValueData.Length > 0)
                        {
                            suffix = $"value data hit{plural}";
                        }
                        else if (p.Object.SimpleSearchValueSlack.Length > 0)
                        {
                            suffix = $"value slack hit{plural}";
                        }
                        else if (p.Object.SimpleSearchKey.Length > 0)
                        {
                            suffix = $"key{plural}";
                        }
                        else if (p.Object.SimpleSearchValue.Length > 0)
                        {
                            suffix = $"value{plural}";
                        }

                        if (p.Object.RegEx)
                        {
                            withRegex = " (via RegEx)";
                        }

                       _logger.Info("");

                        _logger.Info($"Found {hits.Count():N0} {suffix}{withRegex}");

                        DumpStopWatchInfo();

                        
                    }
                    else
                    {
                        _logger.Warn("Nothing to do! =(");
                    }

                    //TODO search deleted?? should only need to look in reg.UnassociatedRegistryValues
                }
                catch (Exception ex)
                {
                    if (!ex.Message.Contains("bad signature"))
                    {
                        _logger.Error($"There was an error: {ex.Message}");
                    }
                }
            }
            /*
            if (p.Object.Directory?.Length > 0)
            {
                _logger.Info("");

                var suffix2 = totalHits == 1 ? "" : "s";
                var suffix3 = hivesWithHits == 1 ? "" : "s";
                var suffix4 = hivesToProcess.Count == 1 ? "" : "s";

                _logger.Info("---------------------------------------------");
                _logger.Info($"Directory: {p.Object.Directory}");
                _logger.Info(
                  $"Found {totalHits:N0} hit{suffix2} in {hivesWithHits:N0} hive{suffix3} out of {hivesToProcess.Count:N0} file{suffix4}");
                _logger.Info($"Total search time: {totalSeconds:N3} seconds");
                _logger.Info("");
            }
            */
        }