public void Dispose() { var exts = new [] { ".md", ".exe" }; Directory.Delete(Path.Combine(WorkingDirectory, ID), true); Profiles.Do(p => { foreach (var ext in exts) { var path = Path.Combine(Directory.GetCurrentDirectory(), p + ext); if (File.Exists(path)) { File.Delete(path); } } }); }
private static void DeleteDirectory(string path) { Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories) .DoProgress("Cleaning VFS Files", file => { try { var fi = new FileInfo(file); fi.Attributes &= ~FileAttributes.ReadOnly; File.Delete(file); } catch (Exception ex) { Utils.Log(ex.ToString()); } }); Directory.EnumerateDirectories(path, DirectoryEnumerationOptions.Recursive) .OrderByDescending(d => d.Length) .DoProgress("Cleaning VFS Folders", folder => { try { if (!Directory.Exists(folder)) { return; } var di = new DirectoryInfo(folder); di.Attributes &= ~FileAttributes.ReadOnly; Directory.Delete(path, true); } catch (Exception ex) { Utils.Log(ex.ToString()); } }); }
public void SetVolumeMountPoint() { Console.WriteLine("Volume.SetVolumeMountPoint()\n"); if (!IsAdmin()) { Assert.Fail(); } #region Logical Drives int cnt = 0; string destFolder = Path.Combine(TempFolder, "Volume.SetVolumeMountPoint()-" + Path.GetRandomFileName()); Directory.CreateDirectory(destFolder); string guid = Volume.GetUniqueVolumeNameForPath(SysDrive); try { StopWatcher(true); Volume.SetVolumeMountPoint(destFolder, guid); Console.WriteLine( "\t#{0:000}\tSystem Drive: [{1}]\tGUID: [{2}]\n\t\tDestination : [{3}]\n\t\tCreated Mount Point.\n\t{4}", ++cnt, SysDrive, guid, destFolder, Reporter(true)); Console.WriteLine("\n"); EnumerateVolumeMountPoints(); Console.WriteLine("\n\nFile.GetLinkTargetInfo()"); LinkTargetInfo lti = File.GetLinkTargetInfo(destFolder); Assert.IsTrue(!string.IsNullOrWhiteSpace(lti.PrintName)); Assert.IsTrue(!string.IsNullOrWhiteSpace(lti.SubstituteName)); Assert.IsTrue(Dump(lti, -14), "Unable to dump object."); // Cleanup. StopWatcher(true); bool deleteOk = false; try { Volume.DeleteVolumeMountPoint(destFolder); deleteOk = true; } catch (Exception ex) { Console.WriteLine("\nCaught Exception: [{0}]\n", ex.Message.Replace(Environment.NewLine, " ")); } Console.WriteLine("\n\nVolume.DeleteVolumeMountPoint() (Should be True): [{0}]\tFolder: [{1}]\n{2}\n", deleteOk, destFolder, Reporter()); Directory.Delete(destFolder, true, true); Assert.IsTrue(deleteOk && !Directory.Exists(destFolder)); EnumerateVolumeMountPoints(); } catch (Exception ex) { Console.WriteLine("\nCaught Exception: [{0}]\n", ex.Message.Replace(Environment.NewLine, " ")); cnt = 0; } finally { // Always remove mount point. // Experienced: CCleaner deletes through mount points! try { Volume.DeleteVolumeMountPoint(destFolder); } catch { } } Assert.IsTrue(cnt > 0, "Nothing was enumerated."); #endregion // Logical Drives }
// Pattern: <class>_<function>_<scenario>_<expected result> #region Unit Tests private void Dump83Path(bool isLocal) { #region Setup Console.WriteLine("\n=== TEST {0} ===", isLocal ? UnitTestConstants.Local : UnitTestConstants.Network); var myLongPath = Path.GetTempPath("My Long Data File Or Directory"); if (!isLocal) { myLongPath = Path.LocalToUnc(myLongPath); } Console.WriteLine("\nInput Path: [{0}]\n", myLongPath); #endregion // Setup #region File string short83Path; try { using (File.Create(myLongPath)) UnitTestConstants.StopWatcher(true); short83Path = Path.GetShort83Path(myLongPath); Console.WriteLine("Short 8.3 file path : [{0}]\t\t\t{1}", short83Path, UnitTestConstants.Reporter(true)); Assert.IsTrue(!short83Path.Equals(myLongPath)); Assert.IsTrue(short83Path.EndsWith(@"~1")); UnitTestConstants.StopWatcher(true); var longFrom83Path = Path.GetLongFrom83ShortPath(short83Path); Console.WriteLine("Long path from 8.3 path: [{0}]{1}", longFrom83Path, UnitTestConstants.Reporter(true)); Assert.IsTrue(longFrom83Path.Equals(myLongPath)); Assert.IsFalse(longFrom83Path.EndsWith(@"~1")); } catch (Exception ex) { Console.WriteLine("Caught (unexpected) {0}: [{1}]", ex.GetType().FullName, ex.Message.Replace(Environment.NewLine, " ")); } finally { if (File.Exists(myLongPath)) { File.Delete(myLongPath); } } Console.WriteLine(); #endregion // File #region Directory try { Directory.CreateDirectory(myLongPath); UnitTestConstants.StopWatcher(true); short83Path = Path.GetShort83Path(myLongPath); Console.WriteLine("Short 8.3 directory path: [{0}]\t\t\t{1}", short83Path, UnitTestConstants.Reporter(true)); Assert.IsFalse(short83Path.Equals(myLongPath)); Assert.IsTrue(short83Path.EndsWith(@"~1")); UnitTestConstants.StopWatcher(true); var longFrom83Path = Path.GetLongFrom83ShortPath(short83Path); Console.WriteLine("Long path from 8.3 path : [{0}]{1}", longFrom83Path, UnitTestConstants.Reporter(true)); Assert.IsTrue(longFrom83Path.Equals(myLongPath)); Assert.IsFalse(longFrom83Path.EndsWith(@"~1")); } catch (Exception ex) { Console.WriteLine("Caught (unexpected) {0}: [{1}]", ex.GetType().FullName, ex.Message.Replace(Environment.NewLine, " ")); } finally { if (Directory.Exists(myLongPath)) { Directory.Delete(myLongPath); } } Console.WriteLine(); #endregion // Directory }
private void DumpGetSetAttributes(bool isLocal) { Console.WriteLine("\n=== TEST {0} ===", isLocal ? UnitTestConstants.Local : UnitTestConstants.Network); var tmp = Path.Combine(Path.GetTempPath(), "File.SetAttributes()-" + Path.GetRandomFileName()); var tempPath = isLocal ? tmp : Path.LocalToUnc(tmp); var sys32 = isLocal ? UnitTestConstants.SysRoot32 : Path.LocalToUnc(UnitTestConstants.SysRoot32); Console.WriteLine("\nInput Path: [{0}]", sys32); // Just enumerate and compare attributes in folder: C:\Windows\System32 foreach (var file in Directory.EnumerateFiles(sys32)) { var actual = File.GetAttributes(file); var expected = System.IO.File.GetAttributes(file); Assert.AreEqual(expected, actual, "AlphaFS != System.IO"); } Console.WriteLine("\nInput Path: [{0}]", tempPath); // Create some folders and files. UnitTestConstants.CreateDirectoriesAndFiles(tempPath, 10, true); var apply = FileAttributes.Hidden | FileAttributes.Archive | FileAttributes.System | FileAttributes.ReadOnly; Console.WriteLine("\nSetAttributes(): [{0}]", apply); var allOk = true; var cnt = 0; UnitTestConstants.StopWatcher(true); foreach (var file in Directory.EnumerateFiles(tempPath)) { try { File.SetAttributes(file, apply); var actual = File.GetAttributes(file); var expected = System.IO.File.GetAttributes(file); Console.WriteLine("\n\t#{0:000}\tFile : [{1}]\n\t\tAlphaFS : [{2}]\n\t\tSystem.IO: [{3}]", ++cnt, file, expected, actual); if (cnt == 0) { Assert.Inconclusive("Nothing was enumerated, but it was expected."); } Assert.AreEqual(expected, actual, "AlphaFS != System.IO"); } catch (Exception ex) { allOk = false; Console.WriteLine("\n\tCaught (unexpected) {0}: [{1}]", ex.GetType().FullName, ex.Message.Replace(Environment.NewLine, " ")); } } Console.WriteLine(); Console.WriteLine(UnitTestConstants.Reporter()); Assert.IsTrue(allOk); apply = FileAttributes.Normal; Console.WriteLine("\nSetAttributes(): [{0}]", apply); allOk = true; cnt = 0; UnitTestConstants.StopWatcher(true); foreach (var file in Directory.EnumerateFiles(tempPath)) { try { File.SetAttributes(file, apply); var actual = File.GetAttributes(file); var expected = System.IO.File.GetAttributes(file); Console.WriteLine("\n\t#{0:000}\tFile : [{1}]\n\t\tAlphaFS : [{2}]\n\t\tSystem.IO: [{3}]", ++cnt, file, expected, actual); if (cnt == 0) { Assert.Inconclusive("Nothing was enumerated, but it was expected."); } Assert.AreEqual(expected, actual, "AlphaFS != System.IO"); } catch (Exception ex) { allOk = false; Console.WriteLine("\n\tCaught (unexpected) {0}: [{1}]", ex.GetType().FullName, ex.Message.Replace(Environment.NewLine, " ")); } } Console.WriteLine(); Console.WriteLine(UnitTestConstants.Reporter()); Directory.Delete(tempPath, true); Assert.IsFalse(Directory.Exists(tempPath), "Cleanup failed: Directory should have been removed."); Assert.IsTrue(allOk); Console.WriteLine(); }
private static void Main(string[] args) { ExceptionlessClient.Default.Startup("tYeWS6A5K5uItgpB44dnNy2qSb2xJxiQWRRGWebq"); SetupNLog(); _logger = LogManager.GetLogger("EvtxECmd"); _fluentCommandLineParser = new FluentCommandLineParser <ApplicationArguments> { IsCaseSensitive = false }; _fluentCommandLineParser.Setup(arg => arg.File) .As('f') .WithDescription("File to process. This or -d is required\r\n"); _fluentCommandLineParser.Setup(arg => arg.Directory) .As('d') .WithDescription("Directory to process that contains evtx files. This or -f is required"); _fluentCommandLineParser.Setup(arg => arg.CsvDirectory) .As("csv") .WithDescription( "Directory to save CSV formatted results to."); // This, --json, or --xml required _fluentCommandLineParser.Setup(arg => arg.CsvName) .As("csvf") .WithDescription( "File name to save CSV formatted results to. When present, overrides default name"); _fluentCommandLineParser.Setup(arg => arg.JsonDirectory) .As("json") .WithDescription( "Directory to save JSON formatted results to."); // This, --csv, or --xml required _fluentCommandLineParser.Setup(arg => arg.JsonName) .As("jsonf") .WithDescription( "File name to save JSON formatted results to. When present, overrides default name"); _fluentCommandLineParser.Setup(arg => arg.XmlDirectory) .As("xml") .WithDescription( "Directory to save XML formatted results to."); // This, --csv, or --json required _fluentCommandLineParser.Setup(arg => arg.XmlName) .As("xmlf") .WithDescription( "File name to save XML formatted results to. When present, overrides default name\r\n"); _fluentCommandLineParser.Setup(arg => arg.DateTimeFormat) .As("dt") .WithDescription( "The custom date/time format to use when displaying time stamps. Default is: yyyy-MM-dd HH:mm:ss.fffffff") .SetDefault("yyyy-MM-dd HH:mm:ss.fffffff"); _fluentCommandLineParser.Setup(arg => arg.IncludeIds) .As("inc") .WithDescription( "List of event IDs to process. All others are ignored. Overrides --exc Format is 4624,4625,5410") .SetDefault(string.Empty); _fluentCommandLineParser.Setup(arg => arg.ExcludeIds) .As("exc") .WithDescription( "List of event IDs to IGNORE. All others are included. Format is 4624,4625,5410") .SetDefault(string.Empty); _fluentCommandLineParser.Setup(arg => arg.StartDate) .As("sd") .WithDescription( "Start date for including events (UTC). Anything OLDER than this is dropped. Format should match --dt") .SetDefault(string.Empty); _fluentCommandLineParser.Setup(arg => arg.EndDate) .As("ed") .WithDescription( "End date for including events (UTC). Anything NEWER than this is dropped. Format should match --dt") .SetDefault(string.Empty); _fluentCommandLineParser.Setup(arg => arg.FullJson) .As("fj") .WithDescription( "When true, export all available data when using --json. Default is FALSE.") .SetDefault(false); _fluentCommandLineParser.Setup(arg => arg.PayloadAsJson) .As("pj") .WithDescription( "When true, include event *payload* as json. Default is TRUE.") .SetDefault(true); _fluentCommandLineParser.Setup(arg => arg.Metrics) .As("met") .WithDescription( "When true, show metrics about processed event log. Default is TRUE.\r\n") .SetDefault(true); _fluentCommandLineParser.Setup(arg => arg.MapsDirectory) .As("maps") .WithDescription( "The path where event maps are located. Defaults to 'Maps' folder where program was executed\r\n ") .SetDefault(Path.Combine(BaseDirectory, "Maps")); _fluentCommandLineParser.Setup(arg => arg.Vss) .As("vss") .WithDescription( "Process all Volume Shadow Copies that exist on drive specified by -f or -d . Default is FALSE") .SetDefault(false); _fluentCommandLineParser.Setup(arg => arg.Dedupe) .As("dedupe") .WithDescription( "Deduplicate -f or -d & VSCs based on SHA-1. First file found wins. Default is TRUE\r\n") .SetDefault(true); _fluentCommandLineParser.Setup(arg => arg.Debug) .As("debug") .WithDescription("Show debug information during processing").SetDefault(false); _fluentCommandLineParser.Setup(arg => arg.Trace) .As("trace") .WithDescription("Show trace information during processing\r\n").SetDefault(false); var header = $"EvtxECmd version {Assembly.GetExecutingAssembly().GetName().Version}" + "\r\n\r\nAuthor: Eric Zimmerman ([email protected])" + "\r\nhttps://github.com/EricZimmerman/evtx"; var footer = @"Examples: EvtxECmd.exe -f ""C:\Temp\Application.evtx"" --csv ""c:\temp\out"" --csvf MyOutputFile.csv" + "\r\n\t " + @" EvtxECmd.exe -f ""C:\Temp\Application.evtx"" --csv ""c:\temp\out""" + "\r\n\t " + @" EvtxECmd.exe -f ""C:\Temp\Application.evtx"" --json ""c:\temp\jsonout""" + "\r\n\t " + "\r\n\t" + " Short options (single letter) are prefixed with a single dash. Long commands are prefixed with two dashes\r\n"; _fluentCommandLineParser.SetupHelp("?", "help") .WithHeader(header) .Callback(text => _logger.Info(text + "\r\n" + footer)); var result = _fluentCommandLineParser.Parse(args); if (result.HelpCalled) { return; } if (result.HasErrors) { _logger.Error(""); _logger.Error(result.ErrorText); _fluentCommandLineParser.HelpOption.ShowHelp(_fluentCommandLineParser.Options); return; } if (_fluentCommandLineParser.Object.File.IsNullOrEmpty() && _fluentCommandLineParser.Object.Directory.IsNullOrEmpty()) { _fluentCommandLineParser.HelpOption.ShowHelp(_fluentCommandLineParser.Options); _logger.Warn("-f or -d is required. Exiting"); return; } _logger.Info(header); _logger.Info(""); _logger.Info($"Command line: {string.Join(" ", Environment.GetCommandLineArgs().Skip(1))}\r\n"); if (IsAdministrator() == false) { _logger.Fatal("Warning: Administrator privileges not found!\r\n"); } if (_fluentCommandLineParser.Object.Debug) { LogManager.Configuration.LoggingRules.First().EnableLoggingForLevel(LogLevel.Debug); } if (_fluentCommandLineParser.Object.Trace) { LogManager.Configuration.LoggingRules.First().EnableLoggingForLevel(LogLevel.Trace); } LogManager.ReconfigExistingLoggers(); if (_fluentCommandLineParser.Object.Vss & (IsAdministrator() == false)) { _logger.Error("--vss is present, but administrator rights not found. Exiting\r\n"); return; } var sw = new Stopwatch(); sw.Start(); var ts = DateTimeOffset.UtcNow; _errorFiles = new Dictionary <string, int>(); if (_fluentCommandLineParser.Object.JsonDirectory.IsNullOrEmpty() == false) { if (Directory.Exists(_fluentCommandLineParser.Object.JsonDirectory) == false) { _logger.Warn( $"Path to '{_fluentCommandLineParser.Object.JsonDirectory}' doesn't exist. Creating..."); try { Directory.CreateDirectory(_fluentCommandLineParser.Object.JsonDirectory); } catch (Exception) { _logger.Fatal( $"Unable to create directory '{_fluentCommandLineParser.Object.JsonDirectory}'. Does a file with the same name exist? Exiting"); return; } } var outName = $"{ts:yyyyMMddHHmmss}_EvtxECmd_Output.json"; if (_fluentCommandLineParser.Object.JsonName.IsNullOrEmpty() == false) { outName = Path.GetFileName(_fluentCommandLineParser.Object.JsonName); } var outFile = Path.Combine(_fluentCommandLineParser.Object.JsonDirectory, outName); _logger.Warn($"json output will be saved to '{outFile}'\r\n"); try { _swJson = new StreamWriter(outFile, false, Encoding.UTF8); } catch (Exception) { _logger.Error($"Unable to open '{outFile}'! Is it in use? Exiting!\r\n"); Environment.Exit(0); } JsConfig.DateHandler = DateHandler.ISO8601; } if (_fluentCommandLineParser.Object.XmlDirectory.IsNullOrEmpty() == false) { if (Directory.Exists(_fluentCommandLineParser.Object.XmlDirectory) == false) { _logger.Warn( $"Path to '{_fluentCommandLineParser.Object.XmlDirectory}' doesn't exist. Creating..."); try { Directory.CreateDirectory(_fluentCommandLineParser.Object.XmlDirectory); } catch (Exception) { _logger.Fatal( $"Unable to create directory '{_fluentCommandLineParser.Object.XmlDirectory}'. Does a file with the same name exist? Exiting"); return; } } var outName = $"{ts:yyyyMMddHHmmss}_EvtxECmd_Output.xml"; if (_fluentCommandLineParser.Object.XmlName.IsNullOrEmpty() == false) { outName = Path.GetFileName(_fluentCommandLineParser.Object.XmlName); } var outFile = Path.Combine(_fluentCommandLineParser.Object.XmlDirectory, outName); _logger.Warn($"XML output will be saved to '{outFile}'\r\n"); try { _swXml = new StreamWriter(outFile, false, Encoding.UTF8); } catch (Exception) { _logger.Error($"Unable to open '{outFile}'! Is it in use? Exiting!\r\n"); Environment.Exit(0); } } if (_fluentCommandLineParser.Object.StartDate.IsNullOrEmpty() == false) { if (DateTimeOffset.TryParse(_fluentCommandLineParser.Object.StartDate, out var dt)) { _startDate = dt; _logger.Info($"Setting Start date to '{_startDate.Value.ToUniversalTime().ToString(_fluentCommandLineParser.Object.DateTimeFormat)}'"); } else { _logger.Warn($"Count not parse '{_fluentCommandLineParser.Object.StartDate}' to a valud datetime! Events will not be filtered by Start date!"); } } if (_fluentCommandLineParser.Object.EndDate.IsNullOrEmpty() == false) { if (DateTimeOffset.TryParse(_fluentCommandLineParser.Object.EndDate, out var dt)) { _endDate = dt; _logger.Info($"Setting End date to '{_endDate.Value.ToUniversalTime().ToString(_fluentCommandLineParser.Object.DateTimeFormat)}'"); } else { _logger.Warn($"Count not parse '{_fluentCommandLineParser.Object.EndDate}' to a valud datetime! Events will not be filtered by End date!"); } } if (_startDate.HasValue || _endDate.HasValue) { _logger.Info(""); } if (_fluentCommandLineParser.Object.CsvDirectory.IsNullOrEmpty() == false) { if (Directory.Exists(_fluentCommandLineParser.Object.CsvDirectory) == false) { _logger.Warn( $"Path to '{_fluentCommandLineParser.Object.CsvDirectory}' doesn't exist. Creating..."); try { Directory.CreateDirectory(_fluentCommandLineParser.Object.CsvDirectory); } catch (Exception) { _logger.Fatal( $"Unable to create directory '{_fluentCommandLineParser.Object.CsvDirectory}'. Does a file with the same name exist? Exiting"); return; } } var outName = $"{ts:yyyyMMddHHmmss}_EvtxECmd_Output.csv"; if (_fluentCommandLineParser.Object.CsvName.IsNullOrEmpty() == false) { outName = Path.GetFileName(_fluentCommandLineParser.Object.CsvName); } var outFile = Path.Combine(_fluentCommandLineParser.Object.CsvDirectory, outName); _logger.Warn($"CSV output will be saved to '{outFile}'\r\n"); try { _swCsv = new StreamWriter(outFile, false, Encoding.UTF8); _csvWriter = new CsvWriter(_swCsv); } catch (Exception) { _logger.Error($"Unable to open '{outFile}'! Is it in use? Exiting!\r\n"); Environment.Exit(0); } var foo = _csvWriter.Configuration.AutoMap <EventRecord>(); if (_fluentCommandLineParser.Object.PayloadAsJson == false) { foo.Map(t => t.Payload).Ignore(); } else { foo.Map(t => t.Payload).Index(22); } foo.Map(t => t.RecordPosition).Ignore(); foo.Map(t => t.Size).Ignore(); foo.Map(t => t.Timestamp).Ignore(); foo.Map(t => t.RecordNumber).Index(0); foo.Map(t => t.EventRecordId).Index(1); foo.Map(t => t.TimeCreated).Index(2); foo.Map(t => t.TimeCreated).ConvertUsing(t => $"{t.TimeCreated.ToString(_fluentCommandLineParser.Object.DateTimeFormat)}"); foo.Map(t => t.EventId).Index(3); foo.Map(t => t.Level).Index(4); foo.Map(t => t.Provider).Index(5); foo.Map(t => t.Channel).Index(6); foo.Map(t => t.ProcessId).Index(7); foo.Map(t => t.ThreadId).Index(8); foo.Map(t => t.Computer).Index(9); foo.Map(t => t.UserId).Index(10); foo.Map(t => t.MapDescription).Index(11); foo.Map(t => t.UserName).Index(12); foo.Map(t => t.RemoteHost).Index(13); foo.Map(t => t.PayloadData1).Index(14); foo.Map(t => t.PayloadData2).Index(15); foo.Map(t => t.PayloadData3).Index(16); foo.Map(t => t.PayloadData4).Index(17); foo.Map(t => t.PayloadData5).Index(18); foo.Map(t => t.PayloadData6).Index(19); foo.Map(t => t.ExecutableInfo).Index(20); foo.Map(t => t.SourceFile).Index(21); _csvWriter.Configuration.RegisterClassMap(foo); _csvWriter.WriteHeader <EventRecord>(); _csvWriter.NextRecord(); } if (Directory.Exists(_fluentCommandLineParser.Object.MapsDirectory) == false) { _logger.Warn( $"Maps directory '{_fluentCommandLineParser.Object.MapsDirectory}' does not exist! Event ID maps will not be loaded!!"); } else { _logger.Debug($"Loading maps from '{Path.GetFullPath(_fluentCommandLineParser.Object.MapsDirectory)}'"); var errors = EventLog.LoadMaps(Path.GetFullPath(_fluentCommandLineParser.Object.MapsDirectory)); if (errors) { return; } _logger.Info($"Maps loaded: {EventLog.EventLogMaps.Count:N0}"); } _includeIds = new HashSet <int>(); _excludeIds = new HashSet <int>(); if (_fluentCommandLineParser.Object.ExcludeIds.IsNullOrEmpty() == false) { var excSegs = _fluentCommandLineParser.Object.ExcludeIds.Split(','); foreach (var incSeg in excSegs) { if (int.TryParse(incSeg, out var goodId)) { _excludeIds.Add(goodId); } } } if (_fluentCommandLineParser.Object.IncludeIds.IsNullOrEmpty() == false) { _excludeIds.Clear(); var incSegs = _fluentCommandLineParser.Object.IncludeIds.Split(','); foreach (var incSeg in incSegs) { if (int.TryParse(incSeg, out var goodId)) { _includeIds.Add(goodId); } } } if (_fluentCommandLineParser.Object.Vss) { string driveLetter; if (_fluentCommandLineParser.Object.File.IsEmpty() == false) { driveLetter = Path.GetPathRoot(Path.GetFullPath(_fluentCommandLineParser.Object.File)) .Substring(0, 1); } else { driveLetter = Path.GetPathRoot(Path.GetFullPath(_fluentCommandLineParser.Object.Directory)) .Substring(0, 1); } Helper.MountVss(driveLetter, VssDir); Console.WriteLine(); } if (_fluentCommandLineParser.Object.File.IsNullOrEmpty() == false) { if (File.Exists(_fluentCommandLineParser.Object.File) == false) { _logger.Warn($"'{_fluentCommandLineParser.Object.File}' does not exist! Exiting"); return; } ProcessFile(_fluentCommandLineParser.Object.File); if (_fluentCommandLineParser.Object.Vss) { var vssDirs = Directory.GetDirectories(VssDir); var root = Path.GetPathRoot(Path.GetFullPath(_fluentCommandLineParser.Object.File)); var stem = Path.GetFullPath(_fluentCommandLineParser.Object.File).Replace(root, ""); foreach (var vssDir in vssDirs) { var newPath = Path.Combine(vssDir, stem); if (File.Exists(newPath)) { ProcessFile(newPath); } } } } else { _logger.Info($"Looking for event log files in '{_fluentCommandLineParser.Object.Directory}'"); _logger.Info(""); var f = new DirectoryEnumerationFilters(); f.InclusionFilter = fsei => fsei.Extension.ToUpperInvariant() == ".EVTX"; f.RecursionFilter = entryInfo => !entryInfo.IsMountPoint && !entryInfo.IsSymbolicLink; f.ErrorFilter = (errorCode, errorMessage, pathProcessed) => true; var dirEnumOptions = DirectoryEnumerationOptions.Files | DirectoryEnumerationOptions.Recursive | DirectoryEnumerationOptions.SkipReparsePoints | DirectoryEnumerationOptions.ContinueOnException | DirectoryEnumerationOptions.BasicSearch; var files2 = Directory.EnumerateFileSystemEntries(Path.GetFullPath(_fluentCommandLineParser.Object.Directory), dirEnumOptions, f); foreach (var file in files2) { ProcessFile(file); } if (_fluentCommandLineParser.Object.Vss) { var vssDirs = Directory.GetDirectories(VssDir); Console.WriteLine(); foreach (var vssDir in vssDirs) { var root = Path.GetPathRoot(Path.GetFullPath(_fluentCommandLineParser.Object.Directory)); var stem = Path.GetFullPath(_fluentCommandLineParser.Object.Directory).Replace(root, ""); var target = Path.Combine(vssDir, stem); _logger.Fatal($"\r\nSearching 'VSS{target.Replace($"{VssDir}\\","")}' for event logs..."); var vssFiles = Helper.GetFilesFromPath(target, true, "*.evtx"); foreach (var file in vssFiles) { ProcessFile(file); } } } } _swCsv?.Flush(); _swCsv?.Close(); _swJson?.Flush(); _swJson?.Close(); _swXml?.Flush(); _swXml?.Close(); sw.Stop(); _logger.Info(""); var suff = string.Empty; if (_fileCount != 1) { suff = "s"; } _logger.Error( $"Processed {_fileCount:N0} file{suff} in {sw.Elapsed.TotalSeconds:N4} seconds\r\n"); if (_errorFiles.Count > 0) { _logger.Info(""); _logger.Error("Files with errors"); foreach (var errorFile in _errorFiles) { _logger.Info($"'{errorFile.Key}' error count: {errorFile.Value:N0}"); } _logger.Info(""); } if (_fluentCommandLineParser.Object.Vss) { if (Directory.Exists(VssDir)) { foreach (var directory in Directory.GetDirectories(VssDir)) { Directory.Delete(directory); } Directory.Delete(VssDir, true, true); } } }
private void Directory_EnumerateAlternateDataStreams(bool isNetwork) { UnitTestConstants.PrintUnitTestHeader(isNetwork); var tempPath = Path.GetTempPath("Directory-EnumerateAlternateDataStreams-" + Path.GetRandomFileName()); if (isNetwork) { tempPath = Path.LocalToUnc(tempPath); } const int defaultStreamsDirectory = 0; // The default number of data streams for a folder. Console.WriteLine("\nInput Directory Path: [{0}]", tempPath); Console.WriteLine("\nA directory is created and {0} streams are added.", UnitTestConstants.AllStreams.Count()); try { var di = new DirectoryInfo(tempPath); di.Create(); var currentNumberofStreams = di.EnumerateAlternateDataStreams().Count(); Assert.AreEqual(defaultStreamsDirectory, currentNumberofStreams, "Total amount of default streams do not match."); Assert.AreEqual(currentNumberofStreams, Directory.EnumerateAlternateDataStreams(tempPath).Count(), "Total amount of Directory.EnumerateAlternateDataStreams() streams do not match."); Assert.AreEqual(currentNumberofStreams, di.EnumerateAlternateDataStreams().Count(), "Total amount of DirectoryInfo() streams do not match."); // Create alternate data streams. // Because of the colon, you must supply a full path and use PathFormat.FullPath or PathFormat.LongFullPath, // to prevent a: "NotSupportedException: path is in an invalid format." exception. File.WriteAllLines(tempPath + Path.StreamSeparator + UnitTestConstants.MyStream, UnitTestConstants.StreamArrayContent, PathFormat.FullPath); File.WriteAllText(tempPath + Path.StreamSeparator + UnitTestConstants.MyStream2, UnitTestConstants.StreamStringContent, PathFormat.FullPath); var newNumberofStreams = Directory.EnumerateAlternateDataStreams(tempPath).Count(); Console.WriteLine("\n\nCurrent stream Count(): [{0}]", newNumberofStreams); // Enumerate all streams from the folder. foreach (var stream in di.EnumerateAlternateDataStreams()) { Assert.IsTrue(UnitTestConstants.Dump(stream, -10)); } // Show the contents of our streams. Console.WriteLine(); foreach (var streamName in UnitTestConstants.AllStreams) { Console.WriteLine("\n\tStream name: [{0}]", streamName); // Because of the colon, you must supply a full path and use PathFormat.FullPath or PathFormat.LongFullPath, // to prevent a: "NotSupportedException: path is in an invalid format." exception. foreach (var line in File.ReadAllLines(tempPath + Path.StreamSeparator + streamName, PathFormat.FullPath)) { Console.WriteLine("\t\t{0}", line); } } } catch (Exception ex) { Console.WriteLine("\n\tCaught (unexpected) {0}: [{1}]", ex.GetType().FullName, ex.Message.Replace(Environment.NewLine, " ")); Assert.IsTrue(false); } finally { Directory.Delete(tempPath); Assert.IsFalse(Directory.Exists(tempPath), "Cleanup failed: Directory should have been removed."); } Console.WriteLine(); }
private static void UpdateFromRepo() { Console.WriteLine(); _logger.Info( "Checking for updated maps at https://github.com/EricZimmerman/evtx/tree/master/evtx/Maps..."); Console.WriteLine(); var archivePath = Path.Combine(BaseDirectory, "____master.zip"); if (File.Exists(archivePath)) { File.Delete(archivePath); } using (var client = new WebClient()) { ServicePointManager.Expect100Continue = true; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; client.DownloadFile("https://github.com/EricZimmerman/evtx/archive/master.zip", archivePath); } var fff = new FastZip(); if (Directory.Exists(Path.Combine(BaseDirectory, "Maps")) == false) { Directory.CreateDirectory(Path.Combine(BaseDirectory, "Maps")); } var directoryFilter = "Maps"; // Will prompt to overwrite if target file names already exist fff.ExtractZip(archivePath, BaseDirectory, FastZip.Overwrite.Always, null, null, directoryFilter, true); if (File.Exists(archivePath)) { File.Delete(archivePath); } var newMapPath = Path.Combine(BaseDirectory, "evtx-master", "evtx", "Maps"); var orgMapPath = Path.Combine(BaseDirectory, "Maps"); var newMaps = Directory.GetFiles(newMapPath); var newlocalMaps = new List <string>(); var updatedlocalMaps = new List <string>(); if (File.Exists(Path.Combine(orgMapPath, "Security_4624.map"))) { _logger.Warn($"Old map format found. Zipping to '!!oldMaps.zip' and cleaning up old maps"); //old maps found, so zip em first var oldZip = Path.Combine(orgMapPath, "!!oldMaps.zip"); fff.CreateZip(oldZip, orgMapPath, false, @"\.map$"); foreach (var m in Directory.GetFiles(orgMapPath, "*.map")) { File.Delete(m); } } if (File.Exists(Path.Combine(orgMapPath, "!!!!README.txt"))) { File.Delete(Path.Combine(orgMapPath, "!!!!README.txt")); } foreach (var newMap in newMaps) { var mName = Path.GetFileName(newMap); var dest = Path.Combine(orgMapPath, mName); if (File.Exists(dest) == false) { //new target newlocalMaps.Add(mName); } else { //current destination file exists, so compare to new var fiNew = new FileInfo(newMap); var fi = new FileInfo(dest); if (fiNew.GetHash(HashType.SHA1) != fi.GetHash(HashType.SHA1)) { //updated file updatedlocalMaps.Add(mName); } } File.Copy(newMap, dest, CopyOptions.None); } if (newlocalMaps.Count > 0 || updatedlocalMaps.Count > 0) { _logger.Fatal("Updates found!"); Console.WriteLine(); if (newlocalMaps.Count > 0) { _logger.Error("New maps"); foreach (var newLocalMap in newlocalMaps) { _logger.Info(Path.GetFileNameWithoutExtension(newLocalMap)); } Console.WriteLine(); } if (updatedlocalMaps.Count > 0) { _logger.Error("Updated maps"); foreach (var um in updatedlocalMaps) { _logger.Info(Path.GetFileNameWithoutExtension(um)); } Console.WriteLine(); } Console.WriteLine(); } else { Console.WriteLine(); _logger.Info("No new maps available"); Console.WriteLine(); } Directory.Delete(Path.Combine(BaseDirectory, "evtx-master"), true); }
public void AlphaFS_Volume_SetVolumeMountPoint() { Console.WriteLine("Volume.SetVolumeMountPoint()"); if (!UnitTestConstants.IsAdmin()) { Assert.Inconclusive(); } #region Logical Drives var cnt = 0; var destFolder = Path.Combine(TempFolder, "Volume.SetVolumeMountPoint()-" + Path.GetRandomFileName()); Directory.CreateDirectory(destFolder); var guid = Volume.GetUniqueVolumeNameForPath(UnitTestConstants.SysDrive); try { UnitTestConstants.StopWatcher(true); Volume.SetVolumeMountPoint(destFolder, guid); Console.WriteLine( "\t#{0:000}\tSystem Drive: [{1}]\tGUID: [{2}]\n\t\tDestination : [{3}]\n\t\tCreated Mount Point.\n\t{4}", ++cnt, UnitTestConstants.SysDrive, guid, destFolder, UnitTestConstants.Reporter(true)); Console.WriteLine("\n"); AlphaFS_Volume_EnumerateVolumeMountPoints(); Console.WriteLine("\n\nFile.GetLinkTargetInfo()"); var lti = File.GetLinkTargetInfo(destFolder); Assert.IsTrue(!string.IsNullOrWhiteSpace(lti.PrintName)); Assert.IsTrue(!string.IsNullOrWhiteSpace(lti.SubstituteName)); Assert.IsTrue(UnitTestConstants.Dump(lti, -14), "Unable to dump object."); // Cleanup. UnitTestConstants.StopWatcher(true); var deleteOk = false; try { Volume.DeleteVolumeMountPoint(destFolder); deleteOk = true; } catch (Exception ex) { Console.WriteLine("\nCaught (unexpected) {0}: [{1}]", ex.GetType().FullName, ex.Message.Replace(Environment.NewLine, " ")); } Console.WriteLine("\n\nVolume.DeleteVolumeMountPoint() (Should be True): [{0}]\tFolder: [{1}]\n{2}\n", deleteOk, destFolder, UnitTestConstants.Reporter()); Directory.Delete(destFolder, true, true); Assert.IsTrue(deleteOk && !Directory.Exists(destFolder)); AlphaFS_Volume_EnumerateVolumeMountPoints(); } catch (Exception ex) { cnt = 0; Console.WriteLine("\nCaught (unexpected) {0}: [{1}]", ex.GetType().FullName, ex.Message.Replace(Environment.NewLine, " ")); } finally { // Always remove mount point. // Experienced: CCleaner deletes through mount points! try { Volume.DeleteVolumeMountPoint(destFolder); } catch { } } if (cnt == 0) { Assert.Inconclusive("Nothing was enumerated, but it was expected."); } #endregion // Logical Drives }
private void DumpEnableDisableEncryption(bool isLocal) { Console.WriteLine("\n=== TEST {0} ===", isLocal ? UnitTestConstants.Local : UnitTestConstants.Network); var tempPath = Path.Combine(Path.GetTempPath(), "Directory.EnableDisableEncryption()-" + Path.GetRandomFileName()); if (!isLocal) { tempPath = Path.LocalToUnc(tempPath); } Console.WriteLine("\nInput Directory Path: [{0}]", tempPath); const string disabled = "Disable=0"; const string enabled = "Disable=1"; var lineDisable = string.Empty; var deskTopIni = Path.Combine(tempPath, "Desktop.ini"); Directory.CreateDirectory(tempPath); var actual = File.GetAttributes(tempPath); var report = string.Empty; var action = false; try { UnitTestConstants.StopWatcher(true); Directory.EnableEncryption(tempPath); report = UnitTestConstants.Reporter(true); action = true; } catch (Exception ex) { Console.WriteLine("\n\tCaught (UNEXPECTED) {0}: [{1}]", ex.GetType().FullName, ex.Message.Replace(Environment.NewLine, " ")); } Assert.IsTrue(action, "Encryption should be True"); // Read filestream contents, get the last line. using (var streamRead = File.OpenText(deskTopIni)) { string line; while ((line = streamRead.ReadLine()) != null) { lineDisable = line; } } action = lineDisable.Equals(disabled); Console.WriteLine("\nEnableEncryption() (Should be True): [{0}]", action); Console.WriteLine("File Desktop.ini contents: [{0}]\t{1}", lineDisable, report); Assert.IsTrue(action, "Encryption should be True"); Assert.IsTrue(File.Exists(deskTopIni), "Desktop.ini should Exist"); action = false; try { UnitTestConstants.StopWatcher(true); Directory.DisableEncryption(tempPath); report = UnitTestConstants.Reporter(true); action = true; } catch (Exception ex) { Console.WriteLine("\n\tCaught (UNEXPECTED) {0}: [{1}]", ex.GetType().FullName, ex.Message.Replace(Environment.NewLine, " ")); } Assert.IsTrue(action, "Encryption should be True"); // Read filestream contents, get the last line. using (var streamRead = File.OpenText(deskTopIni)) { string line; while ((line = streamRead.ReadLine()) != null) { lineDisable = line; } } action = lineDisable.Equals(enabled); Console.WriteLine("\nDisableEncryption() (Should be True): [{0}]", action); Console.WriteLine("File Desktop.ini contents: [{0}]\t{1}", lineDisable, report); Assert.IsTrue(action, "Encryption should be True"); Assert.IsTrue(File.Exists(deskTopIni), "Desktop.ini should Exist"); Directory.Delete(tempPath, true); Assert.IsFalse(Directory.Exists(tempPath), "Cleanup failed: Directory should have been removed."); Console.WriteLine(); }
private List <TestVideo> testVideoList = new List <TestVideo>(); // 测试视频(视频名,所在路径) /************************************************************************************/ // 默认构造 public MainWindow() { InitializeComponent(); // 数据绑定 DataContext = alarmImageList; SceneComBox.ItemsSource = Scenes; IncidentComBox.ItemsSource = Incidents; ImageTreeView.ItemsSource = fileTree; // 元数据 if (File.Exists("./MetaData.xml")) { XmlDocument doc = new XmlDocument(); XmlReaderSettings settings = new XmlReaderSettings { IgnoreComments = true }; // 忽略文档里面的注释 XmlReader reader = XmlReader.Create("./MetaData.xml", settings); doc.Load(reader); XmlNode xn = doc.SelectSingleNode("root"); // 根节点 XmlNodeList xnl = xn.ChildNodes; // 根节点的子节点 Scenes.Clear(); Incidents.Clear(); foreach (XmlNode node in xnl) { if (node.Name == "scene") // 场景下拉列表 { XmlNodeList subNodes = node.ChildNodes; foreach (XmlNode item in subNodes) { if (Scenes.Count(f => f.Name == item.Attributes["tag"].Value) == 0) { Scenes.Add(new SceneItem { Display = item.InnerText, Name = item.Attributes["tag"].Value }); } } } if (node.Name == "incident") // 事件下拉列表 { XmlNodeList subNodes = node.ChildNodes; foreach (XmlNode item in subNodes) { if (Incidents.Count(f => f.Name == item.Attributes["tag"].Value) == 0) { Incidents.Add(new IncidentItem { Display = item.InnerText, Name = item.Attributes["tag"].Value }); } } } } reader.Close(); } else { MessageWindow.ShowDialog("Can not read MetaData.xml", this); } // 删除临时数据 if (Directory.Exists("./temp")) { Directory.Delete("./temp", true); } // 恢复上次程序退出前状态 Resume(); }
private static void UpdateFromRepo() { Console.WriteLine(); Log.Information("Checking for updated maps at {Url}...", "https://github.com/EricZimmerman/evtx/tree/master/evtx/Maps"); Console.WriteLine(); var archivePath = Path.Combine(BaseDirectory, "____master.zip"); if (File.Exists(archivePath)) { File.Delete(archivePath); } // using (var client = new WebClient()) // { // ServicePointManager.Expect100Continue = true; // ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; // client.DownloadFile("https://github.com/EricZimmerman/evtx/archive/master.zip", archivePath); // } "https://github.com/EricZimmerman/evtx/archive/master.zip".DownloadFileTo(archivePath); var fff = new FastZip(); if (Directory.Exists(Path.Combine(BaseDirectory, "Maps")) == false) { Directory.CreateDirectory(Path.Combine(BaseDirectory, "Maps")); } var directoryFilter = "Maps"; // Will prompt to overwrite if target file names already exist fff.ExtractZip(archivePath, BaseDirectory, FastZip.Overwrite.Always, null, null, directoryFilter, true); if (File.Exists(archivePath)) { File.Delete(archivePath); } var newMapPath = Path.Combine(BaseDirectory, "evtx-master", "evtx", "Maps"); var orgMapPath = Path.Combine(BaseDirectory, "Maps"); var newMaps = Directory.GetFiles(newMapPath); var newLocalMaps = new List <string>(); var updatedLocalMaps = new List <string>(); if (File.Exists(Path.Combine(orgMapPath, "Security_4624.map"))) { Log.Warning("Old map format found. Zipping to {Old} and cleaning up old maps", "!!oldMaps.zip"); //old maps found, so zip em first var oldZip = Path.Combine(orgMapPath, "!!oldMaps.zip"); fff.CreateZip(oldZip, orgMapPath, false, @"\.map$"); foreach (var m in Directory.GetFiles(orgMapPath, "*.map")) { File.Delete(m); } } if (File.Exists(Path.Combine(orgMapPath, "!!!!README.txt"))) { File.Delete(Path.Combine(orgMapPath, "!!!!README.txt")); } foreach (var newMap in newMaps) { var mName = Path.GetFileName(newMap); var dest = Path.Combine(orgMapPath, mName); if (File.Exists(dest) == false) { //new target newLocalMaps.Add(mName); } else { //current destination file exists, so compare to new var s1 = new StreamReader(newMap); var newSha = Helper.GetSha1FromStream(s1.BaseStream, 0); var s2 = new StreamReader(dest); var destSha = Helper.GetSha1FromStream(s2.BaseStream, 0); s2.Close(); s1.Close(); if (newSha != destSha) { //updated file updatedLocalMaps.Add(mName); } } #if !NET6_0 File.Copy(newMap, dest, CopyOptions.None); #else File.Copy(newMap, dest, true); #endif } if (newLocalMaps.Count > 0 || updatedLocalMaps.Count > 0) { Log.Information("Updates found!"); Console.WriteLine(); if (newLocalMaps.Count > 0) { Log.Information("New maps"); foreach (var newLocalMap in newLocalMaps) { Log.Information("{File}", Path.GetFileNameWithoutExtension(newLocalMap)); } Console.WriteLine(); } if (updatedLocalMaps.Count > 0) { Log.Information("Updated maps"); foreach (var um in updatedLocalMaps) { Log.Information("{File}", Path.GetFileNameWithoutExtension(um)); } Console.WriteLine(); } Console.WriteLine(); } else { Console.WriteLine(); Log.Information("No new maps available"); Console.WriteLine(); } Directory.Delete(Path.Combine(BaseDirectory, "evtx-master"), true); }
private static void DoWork(string f, string d, string csv, string csvf, string json, string jsonf, string xml, string xmlf, string dt, string inc, string exc, string sd, string ed, bool fj, int tdt, bool met, string maps, bool vss, bool dedupe, bool sync, bool debug, bool trace) { var levelSwitch = new LoggingLevelSwitch(); _activeDateTimeFormat = dt; var formatter = new DateTimeOffsetFormatter(CultureInfo.CurrentCulture); var template = "{Message:lj}{NewLine}{Exception}"; if (debug) { levelSwitch.MinimumLevel = LogEventLevel.Debug; template = "[{Timestamp:HH:mm:ss.fff} {Level:u3}] {Message:lj}{NewLine}{Exception}"; } if (trace) { levelSwitch.MinimumLevel = LogEventLevel.Verbose; template = "[{Timestamp:HH:mm:ss.fff} {Level:u3}] {Message:lj}{NewLine}{Exception}"; } var conf = new LoggerConfiguration() .WriteTo.Console(outputTemplate: template, formatProvider: formatter) .MinimumLevel.ControlledBy(levelSwitch); Log.Logger = conf.CreateLogger(); if (sync) { try { Log.Information("{Header}", Header); UpdateFromRepo(); } catch (Exception e) { Log.Error(e, "There was an error checking for updates: {Message}", e.Message); } Environment.Exit(0); } if (f.IsNullOrEmpty() && d.IsNullOrEmpty()) { var helpBld = new HelpBuilder(LocalizationResources.Instance, Console.WindowWidth); var hc = new HelpContext(helpBld, _rootCommand, Console.Out); helpBld.Write(hc); Log.Warning("-f or -d is required. Exiting"); Console.WriteLine(); return; } Log.Information("{Header}", Header); Console.WriteLine(); Log.Information("Command line: {Args}", string.Join(" ", Environment.GetCommandLineArgs().Skip(1))); Console.WriteLine(); if (IsAdministrator() == false) { Log.Warning("Warning: Administrator privileges not found!"); Console.WriteLine(); } if (vss & !RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { vss = false; Log.Warning("{Vss} not supported on non-Windows platforms. Disabling...", "--vss"); Console.WriteLine(); } if (vss & (IsAdministrator() == false)) { Log.Error("{Vss} is present, but administrator rights not found. Exiting", "--vss"); Console.WriteLine(); return; } var sw = new Stopwatch(); sw.Start(); var ts = DateTimeOffset.UtcNow; _errorFiles = new Dictionary <string, int>(); if (json.IsNullOrEmpty() == false) { if (Directory.Exists(json) == false) { Log.Information("Path to {Json} doesn't exist. Creating...", json); try { Directory.CreateDirectory(json); } catch (Exception ex) { Log.Fatal(ex, "Unable to create directory {Json}. Does a file with the same name exist? Exiting", json); Console.WriteLine(); return; } } var outName = $"{ts:yyyyMMddHHmmss}_EvtxECmd_Output.json"; if (jsonf.IsNullOrEmpty() == false) { outName = Path.GetFileName(jsonf); } var outFile = Path.Combine(json, outName); Log.Information("json output will be saved to {OutFile}", outFile); Console.WriteLine(); try { _swJson = new StreamWriter(outFile, false, Encoding.UTF8); } catch (Exception ex) { Log.Error(ex, "Unable to open {OutFile}! Is it in use? Exiting!", outFile); Console.WriteLine(); Environment.Exit(0); } JsConfig.DateHandler = DateHandler.ISO8601; } if (xml.IsNullOrEmpty() == false) { if (Directory.Exists(xml) == false) { Log.Information("Path to {Xml} doesn't exist. Creating...", xml); try { Directory.CreateDirectory(xml); } catch (Exception ex) { Log.Fatal(ex, "Unable to create directory {Xml}. Does a file with the same name exist? Exiting", xml); return; } } var outName = $"{ts:yyyyMMddHHmmss}_EvtxECmd_Output.xml"; if (xmlf.IsNullOrEmpty() == false) { outName = Path.GetFileName(xmlf); } var outFile = Path.Combine(xml, outName); Log.Information("XML output will be saved to {OutFile}", outFile); Console.WriteLine(); try { _swXml = new StreamWriter(outFile, false, Encoding.UTF8); } catch (Exception ex) { Log.Error(ex, "Unable to open {OutFile}! Is it in use? Exiting!", outFile); Console.WriteLine(); Environment.Exit(0); } } if (sd.IsNullOrEmpty() == false) { if (DateTimeOffset.TryParse(sd, null, DateTimeStyles.AssumeUniversal, out var dateTimeOffset)) { _startDate = dateTimeOffset; Log.Information("Setting Start date to {StartDate}", _startDate.Value); } else { Log.Warning("Could not parse {Sd} to a valid datetime! Events will not be filtered by Start date!", sd); } } if (ed.IsNullOrEmpty() == false) { if (DateTimeOffset.TryParse(ed, null, DateTimeStyles.AssumeUniversal, out var dateTimeOffset)) { _endDate = dateTimeOffset; Log.Information("Setting End date to {EndDate}", _endDate.Value); } else { Log.Warning("Could not parse {Ed} to a valid datetime! Events will not be filtered by End date!", ed); } } if (_startDate.HasValue || _endDate.HasValue) { Console.WriteLine(); } if (csv.IsNullOrEmpty() == false) { if (Directory.Exists(csv) == false) { Log.Information( "Path to {Csv} doesn't exist. Creating...", csv); try { Directory.CreateDirectory(csv); } catch (Exception ex) { Log.Fatal(ex, "Unable to create directory {Csv}. Does a file with the same name exist? Exiting", csv); return; } } var outName = $"{ts:yyyyMMddHHmmss}_EvtxECmd_Output.csv"; if (csvf.IsNullOrEmpty() == false) { outName = Path.GetFileName(csvf); } var outFile = Path.Combine(csv, outName); Log.Information("CSV output will be saved to {OutFile}", outFile); Console.WriteLine(); try { _swCsv = new StreamWriter(outFile, false, Encoding.UTF8); var opt = new CsvConfiguration(CultureInfo.InvariantCulture) { ShouldUseConstructorParameters = _ => false }; _csvWriter = new CsvWriter(_swCsv, opt); } catch (Exception ex) { Log.Error(ex, "Unable to open {OutFile}! Is it in use? Exiting!", outFile); Console.WriteLine(); Environment.Exit(0); } var foo = _csvWriter.Context.AutoMap <EventRecord>(); foo.Map(t => t.RecordPosition).Ignore(); foo.Map(t => t.Size).Ignore(); foo.Map(t => t.Timestamp).Ignore(); foo.Map(t => t.RecordNumber).Index(0); foo.Map(t => t.EventRecordId).Index(1); foo.Map(t => t.TimeCreated).Index(2); foo.Map(t => t.TimeCreated).Convert(t => $"{t.Value.TimeCreated.ToString(dt)}"); foo.Map(t => t.EventId).Index(3); foo.Map(t => t.Level).Index(4); foo.Map(t => t.Provider).Index(5); foo.Map(t => t.Channel).Index(6); foo.Map(t => t.ProcessId).Index(7); foo.Map(t => t.ThreadId).Index(8); foo.Map(t => t.Computer).Index(9); foo.Map(t => t.UserId).Index(10); foo.Map(t => t.MapDescription).Index(11); foo.Map(t => t.UserName).Index(12); foo.Map(t => t.RemoteHost).Index(13); foo.Map(t => t.PayloadData1).Index(14); foo.Map(t => t.PayloadData2).Index(15); foo.Map(t => t.PayloadData3).Index(16); foo.Map(t => t.PayloadData4).Index(17); foo.Map(t => t.PayloadData5).Index(18); foo.Map(t => t.PayloadData6).Index(19); foo.Map(t => t.ExecutableInfo).Index(20); foo.Map(t => t.HiddenRecord).Index(21); foo.Map(t => t.SourceFile).Index(22); foo.Map(t => t.Keywords).Index(23); foo.Map(t => t.Payload).Index(24); _csvWriter.Context.RegisterClassMap(foo); _csvWriter.WriteHeader <EventRecord>(); _csvWriter.NextRecord(); } if (Directory.Exists(maps) == false) { Log.Warning("Maps directory {Maps} does not exist! Event ID maps will not be loaded!!", maps); } else { Log.Debug("Loading maps from {Path}", Path.GetFullPath(maps)); var errors = EventLog.LoadMaps(Path.GetFullPath(maps)); if (errors) { return; } Log.Information("Maps loaded: {Count:N0}", EventLog.EventLogMaps.Count); } _includeIds = new HashSet <int>(); _excludeIds = new HashSet <int>(); if (exc.IsNullOrEmpty() == false) { var excSegs = exc.Split(','); foreach (var incSeg in excSegs) { if (int.TryParse(incSeg, out var goodId)) { _excludeIds.Add(goodId); } } } if (inc.IsNullOrEmpty() == false) { _excludeIds.Clear(); var incSegs = inc.Split(','); foreach (var incSeg in incSegs) { if (int.TryParse(incSeg, out var goodId)) { _includeIds.Add(goodId); } } } if (vss) { string driveLetter; if (f.IsEmpty() == false) { driveLetter = Path.GetPathRoot(Path.GetFullPath(f)) .Substring(0, 1); } else { driveLetter = Path.GetPathRoot(Path.GetFullPath(d)) .Substring(0, 1); } Helper.MountVss(driveLetter, VssDir); Console.WriteLine(); } EventLog.TimeDiscrepancyThreshold = tdt; if (f.IsNullOrEmpty() == false) { if (File.Exists(f) == false) { Log.Warning("\t{F} does not exist! Exiting", f); Console.WriteLine(); return; } if (_swXml == null && _swJson == null && _swCsv == null) { //no need for maps Log.Debug("Clearing map collection since no output specified"); EventLog.EventLogMaps.Clear(); } dedupe = false; ProcessFile(Path.GetFullPath(f), dedupe, fj, met); if (vss) { var vssDirs = Directory.GetDirectories(VssDir); var root = Path.GetPathRoot(Path.GetFullPath(f)); var stem = Path.GetFullPath(f).Replace(root, ""); foreach (var vssDir in vssDirs) { var newPath = Path.Combine(vssDir, stem); if (File.Exists(newPath)) { ProcessFile(newPath, dedupe, fj, met); } } } } else { if (Directory.Exists(d) == false) { Log.Warning("\t{D} does not exist! Exiting", d); Console.WriteLine(); return; } Log.Information("Looking for event log files in {D}", d); Console.WriteLine(); #if !NET6_0 var directoryEnumerationFilters = new DirectoryEnumerationFilters { InclusionFilter = fsei => fsei.Extension.ToUpperInvariant() == ".EVTX", RecursionFilter = entryInfo => !entryInfo.IsMountPoint && !entryInfo.IsSymbolicLink, ErrorFilter = (errorCode, errorMessage, pathProcessed) => true }; var dirEnumOptions = DirectoryEnumerationOptions.Files | DirectoryEnumerationOptions.Recursive | DirectoryEnumerationOptions.SkipReparsePoints | DirectoryEnumerationOptions.ContinueOnException | DirectoryEnumerationOptions.BasicSearch; var files2 = Directory.EnumerateFileSystemEntries(Path.GetFullPath(d), dirEnumOptions, directoryEnumerationFilters); #else var enumerationOptions = new EnumerationOptions { IgnoreInaccessible = true, MatchCasing = MatchCasing.CaseInsensitive, RecurseSubdirectories = true, AttributesToSkip = 0 }; var files2 = Directory.EnumerateFileSystemEntries(d, "*.evtx", enumerationOptions); #endif if (_swXml == null && _swJson == null && _swCsv == null) { //no need for maps Log.Debug("Clearing map collection since no output specified"); EventLog.EventLogMaps.Clear(); } foreach (var file in files2) { ProcessFile(file, dedupe, fj, met); } if (vss) { var vssDirs = Directory.GetDirectories(VssDir); Console.WriteLine(); foreach (var vssDir in vssDirs) { var root = Path.GetPathRoot(Path.GetFullPath(d)); var stem = Path.GetFullPath(d).Replace(root, ""); var target = Path.Combine(vssDir, stem); Console.WriteLine(); Log.Information("Searching {Vss} for event logs...", $"VSS{target.Replace($"{VssDir}\\", "")}"); var vssFiles = Helper.GetFilesFromPath(target, "*.evtx", true); foreach (var file in vssFiles) { ProcessFile(file, dedupe, fj, met); } } } } try { _swCsv?.Flush(); _swCsv?.Close(); _swJson?.Flush(); _swJson?.Close(); _swXml?.Flush(); _swXml?.Close(); } catch (Exception e) { Log.Error(e, "Error when flushing output files to disk! Error message: {Message}", e.Message); } sw.Stop(); Console.WriteLine(); if (_fileCount == 1) { Log.Information("Processed {FileCount:N0} file in {TotalSeconds:N4} seconds", _fileCount, sw.Elapsed.TotalSeconds); } else { Log.Information("Processed {FileCount:N0} files in {TotalSeconds:N4} seconds", _fileCount, sw.Elapsed.TotalSeconds); } Console.WriteLine(); if (_errorFiles.Count > 0) { Console.WriteLine(); Log.Information("Files with errors"); foreach (var errorFile in _errorFiles) { Log.Information("{Key} error count: {Value:N0}", errorFile.Key, errorFile.Value); } Console.WriteLine(); } if (vss) { if (Directory.Exists(VssDir)) { foreach (var directory in Directory.GetDirectories(VssDir)) { Directory.Delete(directory); } #if !NET6_0 Directory.Delete(VssDir, true, true); #else Directory.Delete(VssDir, true); #endif } } }
/// <summary> /// The user may already have some files in the OutputFolder. If so we can go through these and /// figure out which need to be updated, deleted, or left alone /// </summary> public async Task OptimizeModlist() { Utils.Log("Optimizing ModList directives"); // Clone the ModList so our changes don't modify the original data ModList = ModList.Clone(); var indexed = ModList.Directives.ToDictionary(d => d.To); UpdateTracker.NextStep("Looking for files to delete"); await Directory.EnumerateFiles(OutputFolder, "*", DirectoryEnumerationOptions.Recursive) .PMap(Queue, UpdateTracker, f => { var relative_to = f.RelativeTo(OutputFolder); Utils.Status($"Checking if ModList file {relative_to}"); if (indexed.ContainsKey(relative_to) || f.IsInPath(DownloadFolder)) { return; } Utils.Log($"Deleting {relative_to} it's not part of this ModList"); File.Delete(f); }); UpdateTracker.NextStep("Looking for unmodified files"); (await indexed.Values.PMap(Queue, UpdateTracker, d => { // Bit backwards, but we want to return null for // all files we *want* installed. We return the files // to remove from the install list. Status($"Optimizing {d.To}"); var path = Path.Combine(OutputFolder, d.To); if (!File.Exists(path)) { return(null); } var fi = new FileInfo(path); if (fi.Length != d.Size) { return(null); } return(path.FileHash() == d.Hash ? d : null); })) .Where(d => d != null) .Do(d => indexed.Remove(d.To)); Utils.Log("Cleaning empty folders"); var expectedFolders = indexed.Keys // We ignore the last part of the path, so we need a dummy file name .Append(Path.Combine(DownloadFolder, "_")) .SelectMany(path => { // Get all the folders and all the folder parents // so for foo\bar\baz\qux.txt this emits ["foo", "foo\\bar", "foo\\bar\\baz"] var split = path.Split('\\'); return(Enumerable.Range(1, split.Length - 1).Select(t => string.Join("\\", split.Take(t)))); }).Distinct() .Select(p => Path.Combine(OutputFolder, p)) .ToHashSet(); try { Directory.EnumerateDirectories(OutputFolder, DirectoryEnumerationOptions.Recursive) .Where(p => !expectedFolders.Contains(p)) .OrderByDescending(p => p.Length) .Do(p => Directory.Delete(p)); } catch (Exception) { // ignored because it's not worth throwing a fit over Utils.Log("Error when trying to clean empty folders. This doesn't really matter."); } UpdateTracker.NextStep("Updating ModList"); Utils.Log($"Optimized {ModList.Directives.Count} directives to {indexed.Count} required"); var requiredArchives = indexed.Values.OfType <FromArchive>() .GroupBy(d => d.ArchiveHashPath[0]) .Select(d => d.Key) .ToHashSet(); ModList.Archives = ModList.Archives.Where(a => requiredArchives.Contains(a.Hash)).ToList(); ModList.Directives = indexed.Values.ToList(); }