public void TestWin10DevEnvPfProperties() { var file = Path.Combine(TestPrefetchMain.Win10Path, @"DEVENV.EXE-854D7862.pf"); var pf = PrefetchFile.Open(file); //PrefetchFile.DumpToJson(pf, true, @"D:\temp\DEVENV.json"); pf.Header.ExecutableFilename.Should().Be("DEVENV.EXE"); pf.Header.Hash.Should().Be("854D7862"); pf.Header.FileSize.Should().Be(380690); pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-13T09: 50:34.6578416-07:00,")); pf.RunCount.Should().Be(54); pf.VolumeCount.Should().Be(1); pf.VolumeInformation[0].DeviceName.Should().Be(@"\VOLUME{01d1217a9c4c6779-8c9f49ec}"); pf.VolumeInformation[0].SerialNumber.Should().Be("8C9F49EC"); pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2015-11-17T13:57:46.2434681-07:00")); pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(516); pf.VolumeInformation[0].DirectoryNames[3].Should() .Be(@"\VOLUME{01d1217a9c4c6779-8c9f49ec}\PROGRAM FILES (X86)\COMMON FILES\MICROSOFT SHARED\MSENV"); pf.VolumeInformation[0].FileReferences.Count.Should().Be(681); pf.Filenames.Count.Should().Be(403); pf.Filenames[3].Should() .Be( @"\VOLUME{01d1217a9c4c6779-8c9f49ec}\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO 14.0\COMMON7\IDE\MICROSOFT.VISUALSTUDIO.ACTIVITIES.DLL"); pf.VolumeInformation[0].FileReferences[6].MFTEntryNumber.Should().Be((ulong)148922); pf.VolumeInformation[0].FileReferences[6].MFTSequenceNumber.Should().Be(1); pf.VolumeInformation[0].FileReferences[8].MFTEntryNumber.Should().Be((ulong)219686); pf.VolumeInformation[0].FileReferences[8].MFTSequenceNumber.Should().Be(2); }
public void TestWin2012R2RegEditPfProperties() { var file = Path.Combine(TestPrefetchMain.Win2012R2Path, @"NOTEPAD.EXE-D8414F97.pf"); var pf = PrefetchFile.Open(file); // PrefetchFile.DumpToJson(pf, true, @"D:\temp\out.json"); pf.Header.ExecutableFilename.Should().Be("NOTEPAD.EXE"); pf.Header.Hash.Should().Be("D8414F97"); pf.Header.FileSize.Should().Be(15320); pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-16T14: 40:31.2944718-07:00")); pf.RunCount.Should().Be(2); pf.VolumeCount.Should().Be(1); pf.VolumeInformation[0].DeviceName.Should().Be(@"\DEVICE\HARDDISKVOLUME2"); pf.VolumeInformation[0].SerialNumber.Should().Be("7450B65F"); pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2016-01-16T15:21:57.7889266-07:00")); pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(7); pf.VolumeInformation[0].DirectoryNames[3].Should() .Be(@"\DEVICE\HARDDISKVOLUME2\WINDOWS\GLOBALIZATION\SORTING"); pf.VolumeInformation[0].FileReferences.Count.Should().Be(35); pf.Filenames.Count.Should().Be(26); pf.Filenames[3].Should().Be(@"\DEVICE\HARDDISKVOLUME2\WINDOWS\SYSTEM32\ADVAPI32.DLL"); //For whatever reason the sequence # is 1 for both of these when looking at the entry # in the MFT using X-Ways pf.VolumeInformation[0].FileReferences[5].MFTEntryNumber.Should().Be((ulong)0); pf.VolumeInformation[0].FileReferences[5].MFTSequenceNumber.Should().Be(null); pf.VolumeInformation[0].FileReferences[1].MFTEntryNumber.Should().Be((ulong)18972); pf.VolumeInformation[0].FileReferences[1].MFTSequenceNumber.Should().Be(null); }
public void TestWin10ChromePfProperties() { var file = Path.Combine(TestPrefetchMain.Win10Path, @"CHROME.EXE-B3BA7868.pf"); var pf = PrefetchFile.Open(file); pf.Header.ExecutableFilename.Should().Be("CHROME.EXE"); pf.Header.Hash.Should().Be("B3BA7868"); pf.Header.FileSize.Should().Be(116042); pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-13T11: 06:55.3344577-07:00")); pf.RunCount.Should().Be(20); pf.VolumeCount.Should().Be(1); pf.VolumeInformation[0].DeviceName.Should().Be(@"\VOLUME{01d1217a9c4c6779-8c9f49ec}"); pf.VolumeInformation[0].SerialNumber.Should().Be("8C9F49EC"); pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2015-11-17T13:57:46.2434681-07:00")); pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(23); pf.VolumeInformation[0].DirectoryNames[3].Should() .Be(@"\VOLUME{01d1217a9c4c6779-8c9f49ec}\PROGRAM FILES (X86)\GOOGLE\CHROME\APPLICATION"); pf.VolumeInformation[0].FileReferences.Count.Should().Be(284); pf.LastRunTimes.Count.Should().Be(8); pf.Filenames.Count.Should().Be(282); pf.Filenames[3].Should().Be(@"\VOLUME{01d1217a9c4c6779-8c9f49ec}\WINDOWS\SYSTEM32\KERNEL32.DLL"); pf.VolumeInformation[0].FileReferences[5].MFTEntryNumber.Should().Be((ulong)55125); pf.VolumeInformation[0].FileReferences[5].MFTSequenceNumber.Should().Be(1); pf.VolumeInformation[0].FileReferences[9].MFTEntryNumber.Should().Be((ulong)117682); pf.VolumeInformation[0].FileReferences[9].MFTSequenceNumber.Should().Be(2); }
public void TestWin8ChromePfProperties() { var file = Path.Combine(TestPrefetchMain.Win8xPath, @"CALC.EXE-77FDF17F.pf"); var pf = PrefetchFile.Open(file); pf.Header.ExecutableFilename.Should().Be("CALC.EXE"); pf.Header.Hash.Should().Be("77FDF17F"); pf.Header.FileSize.Should().Be(22048); pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-16T14: 10:26.0583417-07:00")); pf.RunCount.Should().Be(2); pf.VolumeCount.Should().Be(1); pf.VolumeInformation[0].DeviceName.Should().Be(@"\DEVICE\HARDDISKVOLUME2"); pf.VolumeInformation[0].SerialNumber.Should().Be("C6EE7444"); pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2016-01-16T15:04:54.3519546-07:00")); pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(7); pf.VolumeInformation[0].DirectoryNames[3].Should() .Be(@"\DEVICE\HARDDISKVOLUME2\WINDOWS\GLOBALIZATION\SORTING"); pf.VolumeInformation[0].FileReferences.Count.Should().Be(46); pf.Filenames.Count.Should().Be(37); pf.Filenames[3].Should().Be(@"\DEVICE\HARDDISKVOLUME2\WINDOWS\SYSTEM32\KERNELBASE.DLL"); pf.VolumeInformation[0].FileReferences[5].MFTEntryNumber.Should().Be((ulong)43858); pf.VolumeInformation[0].FileReferences[5].MFTSequenceNumber.Should().Be(1); pf.VolumeInformation[0].FileReferences[9].MFTEntryNumber.Should().Be((ulong)46917); pf.VolumeInformation[0].FileReferences[9].MFTSequenceNumber.Should().Be(1); }
public void TestXPCalcPfProperties() { var file = Path.Combine(TestPrefetchMain.WinXpPath, @"CALC.EXE-02CD573A.pf"); var pf = PrefetchFile.Open(file); // PrefetchFile.DumpToJson(pf,true,@"D:\temp\out.json"); pf.Header.ExecutableFilename.Should().Be("CALC.EXE"); pf.Header.Hash.Should().Be("2CD573A"); pf.Header.FileSize.Should().Be(11332); pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-13T15: 05:51.2812500-07:00")); pf.RunCount.Should().Be(3); pf.VolumeCount.Should().Be(1); pf.VolumeInformation[0].DeviceName.Should().Be(@"\DEVICE\HARDDISKVOLUME1"); pf.VolumeInformation[0].SerialNumber.Should().Be("E0F7E847"); pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2016-01-13T04:17:18.7187500-07:00")); pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(6); pf.VolumeInformation[0].DirectoryNames[3].Should().Be(@"\DEVICE\HARDDISKVOLUME1\WINDOWS\SYSTEM32\"); pf.VolumeInformation[0].FileReferences.Count.Should().Be(36); pf.Filenames.Count.Should().Be(30); pf.Filenames[3].Should().Be(@"\DEVICE\HARDDISKVOLUME1\WINDOWS\SYSTEM32\LOCALE.NLS"); pf.VolumeInformation[0].FileReferences[34].MFTEntryNumber.Should().Be((ulong)126); pf.VolumeInformation[0].FileReferences[34].MFTSequenceNumber.Should().Be(1); }
public void Test2k3CmdPfProperties() { var file = Path.Combine(TestPrefetchMain.Win2k3Path, @"CMD.EXE-087B4001.pf"); var pf = PrefetchFile.Open(file); pf.Header.ExecutableFilename.Should().Be("CMD.EXE"); pf.Header.Hash.Should().Be("87B4001"); pf.Header.FileSize.Should().Be(6002); pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-15T16: 01:40.8750000-07:00")); pf.RunCount.Should().Be(3); pf.VolumeCount.Should().Be(1); pf.VolumeInformation[0].DeviceName.Should().Be(@"\DEVICE\HARDDISKVOLUME1"); pf.VolumeInformation[0].SerialNumber.Should().Be("64BB3469"); pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2016-01-15T08:45:15.8906250-07:00")); pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(4); pf.VolumeInformation[0].DirectoryNames[3].Should().Be(@"\DEVICE\HARDDISKVOLUME1\WINDOWS\SYSTEM32\"); pf.VolumeInformation[0].FileReferences.Count.Should().Be(20); pf.Filenames.Count.Should().Be(16); pf.Filenames[3].Should().Be(@"\DEVICE\HARDDISKVOLUME1\WINDOWS\SYSTEM32\LOCALE.NLS"); pf.VolumeInformation[0].FileReferences[5].MFTEntryNumber.Should().Be((ulong)250); pf.VolumeInformation[0].FileReferences[5].MFTSequenceNumber.Should().Be(1); }
public void TestWin7CalcPfProperties() { var file = Path.Combine(TestPrefetchMain.Win7Path, @"CALC.EXE-77FDF17F.pf"); var pf = PrefetchFile.Open(file); //PrefetchFile.DumpToJson(pf, true, @"D:\temp\win7calc.json"); pf.Header.ExecutableFilename.Should().Be("CALC.EXE"); pf.Header.Hash.Should().Be("77FDF17F"); pf.Header.FileSize.Should().Be(23538); pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-16T13: 27:01.1967500-07:00")); pf.RunCount.Should().Be(2); pf.VolumeCount.Should().Be(1); pf.VolumeInformation[0].DeviceName.Should().Be(@"\DEVICE\HARDDISKVOLUME2"); pf.VolumeInformation[0].SerialNumber.Should().Be("88008C2F"); pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2016-01-16T14:15:18.1093750-07:00")); pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(8); pf.VolumeInformation[0].DirectoryNames[3].Should() .Be(@"\DEVICE\HARDDISKVOLUME2\WINDOWS\GLOBALIZATION\SORTING"); pf.VolumeInformation[0].FileReferences.Count.Should().Be(45); pf.Filenames.Count.Should().Be(37); pf.Filenames[3].Should().Be(@"\DEVICE\HARDDISKVOLUME2\WINDOWS\SYSTEM32\KERNELBASE.DLL"); pf.VolumeInformation[0].FileReferences[2].MFTEntryNumber.Should().Be((ulong)25654); pf.VolumeInformation[0].FileReferences[2].MFTSequenceNumber.Should().Be(1); }
public void InvalidFileShouldThrowException() { var badFile = Path.Combine(BadPath, "notAPrefetch.pf"); Action action = () => PrefetchFile.Open(badFile); action.ShouldThrow <Exception>().WithMessage("Invalid signature! Should be 'SCCA'"); }
public void TestVistaExplorerPfProperties() { var file = Path.Combine(TestPrefetchMain.WinVistaPath, @"EXPLORER.EXE-7A3328DA.pf"); var pf = PrefetchFile.Open(file); pf.Header.ExecutableFilename.Should().Be("EXPLORER.EXE"); pf.Header.Hash.Should().Be("7A3328DA"); pf.Header.FileSize.Should().Be(38470); pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-16T13: 02:00.8326765-07:00")); pf.RunCount.Should().Be(1); pf.VolumeCount.Should().Be(1); pf.VolumeInformation[0].DeviceName.Should().Be(@"\DEVICE\HARDDISKVOLUME1"); pf.VolumeInformation[0].SerialNumber.Should().Be("E8EAB8B5"); pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2016-01-16T13:53:13.1093750-07:00")); pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(13); pf.VolumeInformation[0].DirectoryNames[3].Should().Be(@"\DEVICE\HARDDISKVOLUME1\USERS\PUBLIC"); pf.VolumeInformation[0].FileReferences.Count.Should().Be(84); pf.Filenames.Count.Should().Be(66); pf.Filenames[3].Should().Be(@"\DEVICE\HARDDISKVOLUME1\WINDOWS\SYSTEM32\ADVAPI32.DLL"); pf.VolumeInformation[0].FileReferences[1].MFTEntryNumber.Should().Be((ulong)352); pf.VolumeInformation[0].FileReferences[1].MFTSequenceNumber.Should().Be(null); }
public void TestWin2012RegEditPfProperties() { var file = Path.Combine(TestPrefetchMain.Win2012Path, @"REGEDIT.EXE-90FEEA06.pf"); var pf = PrefetchFile.Open(file); pf.Header.ExecutableFilename.Should().Be("REGEDIT.EXE"); pf.Header.Hash.Should().Be("90FEEA06"); pf.Header.FileSize.Should().Be(22982); pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-16T14: 36:18.7186980-07:00")); pf.RunCount.Should().Be(1); pf.VolumeCount.Should().Be(1); pf.VolumeInformation[0].DeviceName.Should().Be(@"\DEVICE\HARDDISKVOLUME2"); pf.VolumeInformation[0].SerialNumber.Should().Be("2E25F20A"); pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2016-01-16T15:20:46.1666157-07:00")); pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(12); pf.VolumeInformation[0].DirectoryNames[3].Should() .Be(@"\DEVICE\HARDDISKVOLUME2\USERS\ADMINISTRATOR\APPDATA\LOCAL"); pf.VolumeInformation[0].FileReferences.Count.Should().Be(62); pf.Filenames.Count.Should().Be(42); //For whatever reason the sequence # is 1 for both of these when looking at the entry # pf.VolumeInformation[0].FileReferences[5].MFTEntryNumber.Should().Be((ulong)27324); pf.VolumeInformation[0].FileReferences[5].MFTSequenceNumber.Should().Be(null); pf.VolumeInformation[0].FileReferences[9].MFTEntryNumber.Should().Be((ulong)29316); pf.VolumeInformation[0].FileReferences[9].MFTSequenceNumber.Should().Be(null); }
public void TestWin8CmdPfProperties() { var file = Path.Combine(TestPrefetchMain.Win8xPath, @"_CMD.EXE-4A81B364.pf"); var pf = PrefetchFile.Open(file); pf.Header.ExecutableFilename.Should().Be("CMD.EXE"); pf.Header.Hash.Should().Be("4A81B364"); pf.Header.FileSize.Should().Be(8590); pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-16T14: 25:41.5341178-07:00")); pf.RunCount.Should().Be(2); pf.VolumeCount.Should().Be(1); pf.VolumeInformation[0].DeviceName.Should().Be(@"\DEVICE\HARDDISKVOLUME2"); pf.VolumeInformation[0].SerialNumber.Should().Be("A26E529A"); pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2016-01-16T15:15:38.2977678-07:00")); pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(8); pf.VolumeInformation[0].DirectoryNames[3].Should() .Be(@"\DEVICE\HARDDISKVOLUME2\WINDOWS\BRANDING\BASEBRD\EN-US"); pf.VolumeInformation[0].FileReferences.Count.Should().Be(20); pf.Filenames.Count.Should().Be(12); pf.Filenames[3].Should().Be(@"\DEVICE\HARDDISKVOLUME2\WINDOWS\SYSTEM32\KERNELBASE.DLL"); pf.VolumeInformation[0].FileReferences[1].MFTEntryNumber.Should().Be((ulong)44760); pf.VolumeInformation[0].FileReferences[1].MFTSequenceNumber.Should().Be(null); }
public void OneOff() { var f = @"C:\Temp\outLW\vss010\Windows\prefetch\SETUP.EXE-C52DC467.pf"; var pf = PrefetchFile.Open(f); // pf.Should().NotBe(null); }
public void Windows2k3ShouldHaveVersionNumber17() { foreach (var file in Directory.GetFiles(TestPrefetchMain.Win2k3Path, "*.pf")) { var pf = PrefetchFile.Open(file); pf.SourceFilename.Should().Be(file); pf.Header.Version.Should().Be(Version.WinXpOrWin2K3); } }
public void OneOff() { var f = @"C:\temp\fsout.bin"; var ms = new FileStream(f, FileMode.Open); var pf = PrefetchFile.Open(ms, "foo"); pf.RunCount.Should().BeGreaterThan(0); pf.RunCount.Should().Be(3); // pf.Should().NotBe(null); }
public void OneOff() { var f = @"C:\Temp\500sru\POWERSHELL.EXE-767FB1AE.pf"; var ms = new FileStream(f, FileMode.Open, FileAccess.Read); var pf = PrefetchFile.Open(ms, "foo"); var aa = PrefetchFile.Open(f); pf.RunCount.Should().BeGreaterThan(0); pf.RunCount.Should().Be(3); // pf.Should().NotBe(null); }
public void SignatureShouldBeSCCA() { foreach (var allPath in _allPaths) { foreach (var file in Directory.GetFiles(allPath, "*.pf")) { var pf = PrefetchFile.Open(file); pf.Should().NotBe(null); pf.Filenames.Count.Should().Be(pf.FileMetricsCount); pf.VolumeCount.Should().Be(pf.VolumeInformation.Count); pf.Header.Signature.Should().Be("SCCA"); } } }
public void Windows2012ShouldHaveVersionNumber26() { foreach (var file in Directory.GetFiles(TestPrefetchMain.Win2012Path, "*.pf")) { var pf = PrefetchFile.Open(file); pf.SourceFilename.Should().Be(file); pf.Header.Version.Should().Be(Version.Win8xOrWin2012x); } foreach (var file in Directory.GetFiles(TestPrefetchMain.Win2012R2Path, "*.pf")) { var pf = PrefetchFile.Open(file); pf.SourceFilename.Should().Be(file); pf.Header.Version.Should().Be(Version.Win8xOrWin2012x); } }
public void Windows8xShouldHaveVersionNumber26() { foreach (var file in Directory.GetFiles(TestPrefetchMain.Win8xPath, "*.pf")) { var pf = PrefetchFile.Open(file); var totalDirs = 0; foreach (var volumeInfo in pf.VolumeInformation) { totalDirs += volumeInfo.DirectoryNames.Count; } pf.TotalDirectoryCount.Should().Be(totalDirs); pf.SourceFilename.Should().Be(file); pf.Header.Version.Should().Be(Version.Win8xOrWin2012x); } }
public void TestWin10DcodeDecodePfProperties() { var file = Path.Combine(TestPrefetchMain.Win10Path, @"DCODEDCODEDCODEDCODEDCODEDCOD-E65B9FE8.pf"); var pf = PrefetchFile.Open(file); //PrefetchFile.DumpToJson(pf, true, @"D:\temp\DCODEDCODEDCODEDCODEDCODEDCOD.json"); pf.Header.ExecutableFilename.Should().Be("DCODEDCODEDCODEDCODEDCODEDCOD"); pf.Header.Hash.Should().Be("E65B9FE8"); pf.Header.FileSize.Should().Be(33606); pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-13T15: 47:25.7480759-07:00")); pf.RunCount.Should().Be(2); pf.VolumeCount.Should().Be(2); pf.VolumeInformation[0].DeviceName.Should().Be(@"\VOLUME{01d12173f395296c-66f451bc}"); pf.VolumeInformation[0].SerialNumber.Should().Be("66F451BC"); pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2015-11-17T13:10:06.2049644-07:00")); pf.VolumeInformation[1].DeviceName.Should().Be(@"\VOLUME{01d1217a9c4c6779-8c9f49ec}"); pf.VolumeInformation[1].SerialNumber.Should().Be("8C9F49EC"); pf.VolumeInformation[1].CreationTime.Should().Be(DateTimeOffset.Parse("2015-11-17T13:57:46.2434681-07:00")); pf.VolumeInformation[1].DirectoryNames.Count.Should().Be(19); pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(1); pf.VolumeInformation[0].DirectoryNames[0].Should() .Be(@"\VOLUME{01d12173f395296c-66f451bc}\TEMP"); pf.VolumeInformation[0].FileReferences.Count.Should().Be(2); pf.VolumeInformation[1].FileReferences.Count.Should().Be(85); pf.Filenames.Count.Should().Be(57); pf.Filenames[3].Should().Be(@"\VOLUME{01d1217a9c4c6779-8c9f49ec}\WINDOWS\SYSTEM32\KERNEL32.DLL"); pf.VolumeInformation[1].FileReferences[12].MFTEntryNumber.Should().Be((ulong)357876); pf.VolumeInformation[1].FileReferences[12].MFTSequenceNumber.Should().Be(1); pf.VolumeInformation[0].FileReferences[1].MFTEntryNumber.Should().Be((ulong)305846); pf.VolumeInformation[0].FileReferences[1].MFTSequenceNumber.Should().Be(2); }
public void TestWin7DCodePfProperties() { var file = Path.Combine(TestPrefetchMain.Win7Path, @"DCODEDCODEDCODEDCODEDCODEDCOD-9054DA3F.pf"); var pf = PrefetchFile.Open(file); // PrefetchFile.DumpToJson(pf, true, @"D:\temp\win7DCODEDCODEDCODEDCODEDCODEDCOD.json"); pf.Header.ExecutableFilename.Should().Be("DCODEDCODEDCODEDCODEDCODEDCOD"); pf.Header.Hash.Should().Be("9054DA3F"); pf.Header.FileSize.Should().Be(29746); pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-22T09: 23:16.3416250-07:00")); pf.RunCount.Should().Be(5); pf.VolumeCount.Should().Be(2); pf.VolumeInformation[0].DeviceName.Should().Be(@"\DEVICE\HARDDISKVOLUME2"); pf.VolumeInformation[0].SerialNumber.Should().Be("88008C2F"); pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2016-01-16T14:15:18.1093750-07:00")); pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(14); pf.VolumeInformation[0].DirectoryNames[3].Should() .Be(@"\DEVICE\HARDDISKVOLUME2\USERS\E\APPDATA\LOCAL"); pf.VolumeInformation[0].FileReferences.Count.Should().Be(63); pf.VolumeInformation[1].DeviceName.Should().Be(@"\DEVICE\HARDDISKVOLUME3"); pf.VolumeInformation[1].SerialNumber.Should().Be("E892367F"); pf.VolumeInformation[1].CreationTime.Should().Be(DateTimeOffset.Parse("2016-01-22T09:11:36.5781250-07:00")); pf.VolumeInformation[1].DirectoryNames.Count.Should().Be(2); pf.VolumeInformation[1].DirectoryNames[1].Should() .Be(@"\DEVICE\HARDDISKVOLUME3\TEMP\222"); pf.VolumeInformation[1].FileReferences.Count.Should().Be(3); pf.Filenames.Count.Should().Be(50); pf.Filenames[3].Should().Be(@"\DEVICE\HARDDISKVOLUME2\WINDOWS\SYSTEM32\WOW64CPU.DLL"); pf.VolumeInformation[1].FileReferences[1].MFTEntryNumber.Should().Be((ulong)37); pf.VolumeInformation[1].FileReferences[1].MFTSequenceNumber.Should().Be(1); }
private static IPrefetch LoadFile(string pfFile) { if (_fluentCommandLineParser.Object.Quiet == false) { _logger.Warn($"Processing '{pfFile}'"); _logger.Info(""); } var sw = new Stopwatch(); sw.Start(); try { var pf = PrefetchFile.Open(pfFile); if (pf.ParsingError) { _failedFiles.Add($"'{pfFile}' is corrupt and did not parse completely!"); _logger.Fatal($"'{pfFile}' FILE DID NOT PARSE COMPLETELY!\r\n"); } if (_fluentCommandLineParser.Object.Quiet == false) { if (pf.ParsingError) { _logger.Fatal("PARTIAL OUTPUT SHOWN BELOW\r\n"); } var created = _fluentCommandLineParser.Object.LocalTime ? pf.SourceCreatedOn.ToLocalTime() : pf.SourceCreatedOn; var modified = _fluentCommandLineParser.Object.LocalTime ? pf.SourceModifiedOn.ToLocalTime() : pf.SourceModifiedOn; var accessed = _fluentCommandLineParser.Object.LocalTime ? pf.SourceAccessedOn.ToLocalTime() : pf.SourceAccessedOn; _logger.Info($"Created on: {created.ToString(_fluentCommandLineParser.Object.DateTimeFormat)}"); _logger.Info($"Modified on: {modified.ToString(_fluentCommandLineParser.Object.DateTimeFormat)}"); _logger.Info( $"Last accessed on: {accessed.ToString(_fluentCommandLineParser.Object.DateTimeFormat)}"); _logger.Info(""); var dirString = pf.TotalDirectoryCount.ToString(CultureInfo.InvariantCulture); var dd = new string('0', dirString.Length); var dirFormat = $"{dd}.##"; var fString = pf.FileMetricsCount.ToString(CultureInfo.InvariantCulture); var ff = new string('0', fString.Length); var fileFormat = $"{ff}.##"; _logger.Info($"Executable name: {pf.Header.ExecutableFilename}"); _logger.Info($"Hash: {pf.Header.Hash}"); _logger.Info($"File size (bytes): {pf.Header.FileSize:N0}"); _logger.Info($"Version: {GetDescriptionFromEnumValue(pf.Header.Version)}"); _logger.Info(""); _logger.Info($"Run count: {pf.RunCount:N0}"); var lastRun = pf.LastRunTimes.First(); if (_fluentCommandLineParser.Object.LocalTime) { lastRun = lastRun.ToLocalTime(); } _logger.Warn($"Last run: {lastRun.ToString(_fluentCommandLineParser.Object.DateTimeFormat)}"); if (pf.LastRunTimes.Count > 1) { var lastRuns = pf.LastRunTimes.Skip(1).ToList(); if (_fluentCommandLineParser.Object.LocalTime) { for (var i = 0; i < lastRuns.Count; i++) { lastRuns[i] = lastRuns[i].ToLocalTime(); } } var otherRunTimes = string.Join(", ", lastRuns.Select(t => t.ToString(_fluentCommandLineParser.Object.DateTimeFormat))); _logger.Info($"Other run times: {otherRunTimes}"); } // // if (_fluentCommandLineParser.Object.Quiet == false) // { _logger.Info(""); _logger.Info("Volume information:"); _logger.Info(""); var volnum = 0; foreach (var volumeInfo in pf.VolumeInformation) { var localCreate = volumeInfo.CreationTime; if (_fluentCommandLineParser.Object.LocalTime) { localCreate = localCreate.ToLocalTime(); } _logger.Info( $"#{volnum}: Name: {volumeInfo.DeviceName} Serial: {volumeInfo.SerialNumber} Created: {localCreate.ToString(_fluentCommandLineParser.Object.DateTimeFormat)} Directories: {volumeInfo.DirectoryNames.Count:N0} File references: {volumeInfo.FileReferences.Count:N0}"); volnum += 1; } _logger.Info(""); var totalDirs = pf.TotalDirectoryCount; if (pf.Header.Version == Version.WinXpOrWin2K3) { totalDirs = 0; //this has -1 for total directories, so we have to calculate it foreach (var volumeInfo in pf.VolumeInformation) { totalDirs += volumeInfo.DirectoryNames.Count; } } _logger.Info($"Directories referenced: {totalDirs:N0}"); _logger.Info(""); var dirIndex = 0; foreach (var volumeInfo in pf.VolumeInformation) { foreach (var directoryName in volumeInfo.DirectoryNames) { var found = false; foreach (var keyword in _keywords) { if (directoryName.ToLower().Contains(keyword)) { _logger.Fatal($"{dirIndex.ToString(dirFormat)}: {directoryName}"); found = true; break; } } if (!found) { _logger.Info($"{dirIndex.ToString(dirFormat)}: {directoryName}"); } dirIndex += 1; } } _logger.Info(""); _logger.Info($"Files referenced: {pf.Filenames.Count:N0}"); _logger.Info(""); var fileIndex = 0; foreach (var filename in pf.Filenames) { if (filename.Contains(pf.Header.ExecutableFilename)) { _logger.Error($"{fileIndex.ToString(fileFormat)}: {filename}"); } else { var found = false; foreach (var keyword in _keywords) { if (filename.ToLower().Contains(keyword)) { _logger.Fatal($"{fileIndex.ToString(fileFormat)}: {filename}"); found = true; break; } } if (!found) { _logger.Info($"{fileIndex.ToString(fileFormat)}: {filename}"); } } fileIndex += 1; } } sw.Stop(); if (_fluentCommandLineParser.Object.Quiet == false) { _logger.Info(""); } _logger.Info( $"---------- Processed '{pf.SourceFilename}' in {sw.Elapsed.TotalSeconds:N8} seconds ----------"); if (_fluentCommandLineParser.Object.Quiet == false) { _logger.Info("\r\n"); } return(pf); } catch (ArgumentNullException an) { _logger.Error( $"Error opening '{pfFile}'.\r\n\r\nThis appears to be a Windows 10 prefetch file. You must be running Windows 8 or higher to decompress Windows 10 prefetch files"); _logger.Info(""); _failedFiles.Add( $"{pfFile} ==> ({an.Message} (This appears to be a Windows 10 prefetch file. You must be running Windows 8 or higher to decompress Windows 10 prefetch files))"); } catch (Exception ex) { _logger.Error($"Error opening '{pfFile}'. Message: {ex.Message}"); _logger.Info(""); _failedFiles.Add($"{pfFile} ==> ({ex.Message})"); } return(null); }
private static void Main(string[] args) { ExceptionlessClient.Default.Startup("x3MPpeQSBUUsXl3DjekRQ9kYjyN3cr5JuwdoOBpZ"); SetupNLog(); _keywords = new HashSet <string> { "temp", "tmp" }; _logger = LogManager.GetCurrentClassLogger(); if (!CheckForDotnet46()) { _logger.Warn(".net 4.6 not detected. Please install .net 4.6 and try again."); return; } _fluentCommandLineParser = new FluentCommandLineParser <ApplicationArguments> { IsCaseSensitive = false }; _fluentCommandLineParser.Setup(arg => arg.File) .As('f') .WithDescription("File to process. Either this or -d is required"); _fluentCommandLineParser.Setup(arg => arg.Directory) .As('d') .WithDescription("Directory to recursively process. Either this or -f is required"); _fluentCommandLineParser.Setup(arg => arg.Keywords) .As('k') .WithDescription( "Comma separated list of keywords to highlight in output. By default, 'temp' and 'tmp' are highlighted. Any additional keywords will be added to these."); _fluentCommandLineParser.Setup(arg => arg.OutFile) .As('o') .WithDescription( "When specified, save prefetch file bytes to the given path. Useful to look at decompressed Win10 files"); _fluentCommandLineParser.Setup(arg => arg.Quiet) .As('q') .WithDescription( "Do not dump full details about each file processed. Speeds up processing when using --json or --csv\r\n") .SetDefault(false); _fluentCommandLineParser.Setup(arg => arg.JsonDirectory) .As("json") .WithDescription( "Directory to save json representation to. Use --pretty for a more human readable layout"); _fluentCommandLineParser.Setup(arg => arg.CsvDirectory) .As("csv") .WithDescription( "Directory to save CSV results to. Be sure to include the full path in double quotes"); _fluentCommandLineParser.Setup(arg => arg.xHtmlDirectory) .As("html") .WithDescription( "Directory to save xhtml formatted results to. Be sure to include the full path in double quotes"); _fluentCommandLineParser.Setup(arg => arg.JsonPretty) .As("pretty") .WithDescription( "When exporting to json, use a more human readable layout\r\n").SetDefault(false); _fluentCommandLineParser.Setup(arg => arg.CsvSeparator) .As("cs") .WithDescription( "When true, use comma instead of tab for field separator. Default is true").SetDefault(true); _fluentCommandLineParser.Setup(arg => arg.DateTimeFormat) .As("dt") .WithDescription( "The custom date/time format to use when displaying timestamps. See https://goo.gl/CNVq0k for options. Default is: yyyy-MM-dd HH:mm:ss") .SetDefault("yyyy-MM-dd HH:mm:ss"); _fluentCommandLineParser.Setup(arg => arg.PreciseTimestamps) .As("mp") .WithDescription( "When true, display higher precision for timestamps. Default is false").SetDefault(false); var header = $"PECmd version {Assembly.GetExecutingAssembly().GetName().Version}" + "\r\n\r\nAuthor: Eric Zimmerman ([email protected])" + "\r\nhttps://github.com/EricZimmerman/PECmd"; var footer = @"Examples: PECmd.exe -f ""C:\Temp\CALC.EXE-3FBEF7FD.pf""" + "\r\n\t " + @" PECmd.exe -f ""C:\Temp\CALC.EXE-3FBEF7FD.pf"" --json ""D:\jsonOutput"" --jsonpretty" + "\r\n\t " + @" PECmd.exe -d ""C:\Temp"" -k ""system32, fonts""" + "\r\n\t " + @" PECmd.exe -d ""C:\Temp"" --csv ""c:\temp"" --json c:\temp\json" + "\r\n\t " + @" PECmd.exe -d ""C:\Windows\Prefetch""" + "\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 (UsefulExtension.IsNullOrEmpty(_fluentCommandLineParser.Object.File) && UsefulExtension.IsNullOrEmpty(_fluentCommandLineParser.Object.Directory)) { _fluentCommandLineParser.HelpOption.ShowHelp(_fluentCommandLineParser.Options); _logger.Warn("Either -f or -d is required. Exiting"); return; } if (UsefulExtension.IsNullOrEmpty(_fluentCommandLineParser.Object.File) == false && !File.Exists(_fluentCommandLineParser.Object.File)) { _logger.Warn($"File '{_fluentCommandLineParser.Object.File}' not found. Exiting"); return; } if (UsefulExtension.IsNullOrEmpty(_fluentCommandLineParser.Object.Directory) == false && !Directory.Exists(_fluentCommandLineParser.Object.Directory)) { _logger.Warn($"Directory '{_fluentCommandLineParser.Object.Directory}' not found. Exiting"); return; } if (_fluentCommandLineParser.Object.Keywords?.Length > 0) { var kws = _fluentCommandLineParser.Object.Keywords.ToLowerInvariant().Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); foreach (var kw in kws) { _keywords.Add(kw.Trim()); } } if (_fluentCommandLineParser.Object.CsvSeparator) { _exportExt = "csv"; } _logger.Info(header); _logger.Info(""); _logger.Info($"Command line: {string.Join(" ", Environment.GetCommandLineArgs().Skip(1))}"); if (IsAdministrator() == false) { _logger.Fatal("\r\nWarning: Administrator privileges not found!"); } _logger.Info(""); _logger.Info($"Keywords: {string.Join(", ", _keywords)}"); _logger.Info(""); if (_fluentCommandLineParser.Object.PreciseTimestamps) { _fluentCommandLineParser.Object.DateTimeFormat = _preciseTimeFormat; } _processedFiles = new List <IPrefetch>(); _failedFiles = new List <string>(); if (_fluentCommandLineParser.Object.File?.Length > 0) { IPrefetch pf = null; try { pf = LoadFile(_fluentCommandLineParser.Object.File); if (pf != null) { if (_fluentCommandLineParser.Object.OutFile.IsNullOrEmpty() == false) { try { if (Directory.Exists(Path.GetDirectoryName(_fluentCommandLineParser.Object.OutFile)) == false) { Directory.CreateDirectory( Path.GetDirectoryName(_fluentCommandLineParser.Object.OutFile)); } PrefetchFile.SavePrefetch(_fluentCommandLineParser.Object.OutFile, pf); _logger.Info($"Saved prefetch bytes to '{_fluentCommandLineParser.Object.OutFile}'"); } catch (Exception e) { _logger.Error($"Unable to save prefetch file. Error: {e.Message}"); } } _processedFiles.Add(pf); } } catch (UnauthorizedAccessException ex) { _logger.Error( $"Unable to access '{_fluentCommandLineParser.Object.File}'. Are you running as an administrator? Error: {ex.Message}"); } catch (Exception ex) { _logger.Error( $"Error getting prefetch files in '{_fluentCommandLineParser.Object.Directory}'. Error: {ex.Message}"); } } else { _logger.Info($"Looking for prefetch files in '{_fluentCommandLineParser.Object.Directory}'"); _logger.Info(""); string[] pfFiles = null; try { pfFiles = Directory.GetFiles(_fluentCommandLineParser.Object.Directory, "*.pf", SearchOption.AllDirectories); } catch (UnauthorizedAccessException ua) { _logger.Error( $"Unable to access '{_fluentCommandLineParser.Object.Directory}'. Are you running as an administrator? Error: {ua.Message}"); return; } catch (Exception ex) { _logger.Error( $"Error getting prefetch files in '{_fluentCommandLineParser.Object.Directory}'. Error: {ex.Message}"); return; } _logger.Info($"Found {pfFiles.Length:N0} Prefetch files"); _logger.Info(""); var sw = new Stopwatch(); sw.Start(); foreach (var file in pfFiles) { var pf = LoadFile(file); if (pf != null) { _processedFiles.Add(pf); } } sw.Stop(); if (_fluentCommandLineParser.Object.Quiet) { _logger.Info(""); } _logger.Info( $"Processed {pfFiles.Length - _failedFiles.Count:N0} out of {pfFiles.Length:N0} files in {sw.Elapsed.TotalSeconds:N4} seconds"); if (_failedFiles.Count > 0) { _logger.Info(""); _logger.Warn("Failed files"); foreach (var failedFile in _failedFiles) { _logger.Info($" {failedFile}"); } } } if (_processedFiles.Count > 0) { _logger.Info(""); try { CsvWriter csv = null; StreamWriter streamWriter = null; CsvWriter csvTl = null; StreamWriter streamWriterTl = null; if (_fluentCommandLineParser.Object.CsvDirectory?.Length > 0) { var outName = $"{DateTimeOffset.Now:yyyyMMddHHmmss}_PECmd_Output.{_exportExt}"; var outNameTl = $"{DateTimeOffset.Now:yyyyMMddHHmmss}_PECmd_Output_Timeline.{_exportExt}"; var outFile = Path.Combine(_fluentCommandLineParser.Object.CsvDirectory, outName); var outFileTl = Path.Combine(_fluentCommandLineParser.Object.CsvDirectory, outNameTl); if (Directory.Exists(_fluentCommandLineParser.Object.CsvDirectory) == false) { _logger.Warn( $"Path to '{_fluentCommandLineParser.Object.CsvDirectory}' does not exist. Creating..."); Directory.CreateDirectory(_fluentCommandLineParser.Object.CsvDirectory); } _logger.Warn($"CSV output will be saved to '{outFile}'"); _logger.Warn($"CSV time line output will be saved to '{outFileTl}'"); try { streamWriter = new StreamWriter(outFile); csv = new CsvWriter(streamWriter); if (_fluentCommandLineParser.Object.CsvSeparator == false) { csv.Configuration.Delimiter = "\t"; } csv.WriteHeader(typeof(CsvOut)); csv.NextRecord(); streamWriterTl = new StreamWriter(outFileTl); csvTl = new CsvWriter(streamWriterTl); if (_fluentCommandLineParser.Object.CsvSeparator == false) { csvTl.Configuration.Delimiter = "\t"; } csvTl.WriteHeader(typeof(CsvOutTl)); csvTl.NextRecord(); } catch (Exception ex) { _logger.Error( $"Unable to open '{outFile}' for writing. CSV export canceled. Error: {ex.Message}"); } } if (_fluentCommandLineParser.Object.JsonDirectory?.Length > 0) { if (Directory.Exists(_fluentCommandLineParser.Object.JsonDirectory) == false) { _logger.Warn( $"'{_fluentCommandLineParser.Object.JsonDirectory} does not exist. Creating...'"); Directory.CreateDirectory(_fluentCommandLineParser.Object.JsonDirectory); } _logger.Warn($"Saving json output to '{_fluentCommandLineParser.Object.JsonDirectory}'"); } XmlTextWriter xml = null; if (_fluentCommandLineParser.Object.xHtmlDirectory?.Length > 0) { if (Directory.Exists(_fluentCommandLineParser.Object.xHtmlDirectory) == false) { _logger.Warn( $"'{_fluentCommandLineParser.Object.xHtmlDirectory} does not exist. Creating...'"); Directory.CreateDirectory(_fluentCommandLineParser.Object.xHtmlDirectory); } var outDir = Path.Combine(_fluentCommandLineParser.Object.xHtmlDirectory, $"{DateTimeOffset.UtcNow:yyyyMMddHHmmss}_PECmd_Output_for_{_fluentCommandLineParser.Object.xHtmlDirectory.Replace(@":\", "_").Replace(@"\", "_")}"); if (Directory.Exists(outDir) == false) { Directory.CreateDirectory(outDir); } var styleDir = Path.Combine(outDir, "styles"); if (Directory.Exists(styleDir) == false) { Directory.CreateDirectory(styleDir); } File.WriteAllText(Path.Combine(styleDir, "normalize.css"), Resources.normalize); File.WriteAllText(Path.Combine(styleDir, "style.css"), Resources.style); Resources.directories.Save(Path.Combine(styleDir, "directories.png")); Resources.filesloaded.Save(Path.Combine(styleDir, "filesloaded.png")); var outFile = Path.Combine(_fluentCommandLineParser.Object.xHtmlDirectory, outDir, "index.xhtml"); _logger.Warn($"Saving HTML output to '{outFile}'"); xml = new XmlTextWriter(outFile, Encoding.UTF8) { Formatting = Formatting.Indented, Indentation = 4 }; xml.WriteStartDocument(); xml.WriteProcessingInstruction("xml-stylesheet", "href=\"styles/normalize.css\""); xml.WriteProcessingInstruction("xml-stylesheet", "href=\"styles/style.css\""); xml.WriteStartElement("document"); } if (_fluentCommandLineParser.Object.CsvDirectory.IsNullOrEmpty() == false || _fluentCommandLineParser.Object.JsonDirectory.IsNullOrEmpty() == false || _fluentCommandLineParser.Object.xHtmlDirectory.IsNullOrEmpty() == false) { foreach (var processedFile in _processedFiles) { var o = GetCsvFormat(processedFile); try { foreach (var dateTimeOffset in processedFile.LastRunTimes) { var t = new CsvOutTl(); var exePath = processedFile.Filenames.FirstOrDefault( y => y.EndsWith(processedFile.Header.ExecutableFilename)); if (exePath == null) { exePath = processedFile.Header.ExecutableFilename; } t.ExecutableName = exePath; t.RunTime = dateTimeOffset.ToString(_fluentCommandLineParser.Object.DateTimeFormat); csvTl?.WriteRecord(t); csvTl?.NextRecord(); } } catch (Exception ex) { _logger.Error( $"Error getting time line record for '{processedFile.SourceFilename}' to '{_fluentCommandLineParser.Object.CsvDirectory}'. Error: {ex.Message}"); } try { csv?.WriteRecord(o); csv?.NextRecord(); } catch (Exception ex) { _logger.Error( $"Error writing CSV record for '{processedFile.SourceFilename}' to '{_fluentCommandLineParser.Object.CsvDirectory}'. Error: {ex.Message}"); } if (_fluentCommandLineParser.Object.JsonDirectory?.Length > 0) { SaveJson(processedFile, _fluentCommandLineParser.Object.JsonPretty, _fluentCommandLineParser.Object.JsonDirectory); } //XHTML xml?.WriteStartElement("Container"); xml?.WriteElementString("SourceFile", o.SourceFilename); xml?.WriteElementString("SourceCreated", o.SourceCreated); xml?.WriteElementString("SourceModified", o.SourceModified); xml?.WriteElementString("SourceAccessed", o.SourceAccessed); xml?.WriteElementString("LastRun", o.LastRun); xml?.WriteElementString("PreviousRun0", $"{o.PreviousRun0}"); xml?.WriteElementString("PreviousRun1", $"{o.PreviousRun1}"); xml?.WriteElementString("PreviousRun2", $"{o.PreviousRun2}"); xml?.WriteElementString("PreviousRun3", $"{o.PreviousRun3}"); xml?.WriteElementString("PreviousRun4", $"{o.PreviousRun4}"); xml?.WriteElementString("PreviousRun5", $"{o.PreviousRun5}"); xml?.WriteElementString("PreviousRun6", $"{o.PreviousRun6}"); xml?.WriteStartElement("ExecutableName"); xml?.WriteAttributeString("title", "Note: The name of the executable tracked by the pf file"); xml?.WriteString(o.ExecutableName); xml?.WriteEndElement(); xml?.WriteElementString("RunCount", $"{o.RunCount}"); xml?.WriteStartElement("Size"); xml?.WriteAttributeString("title", "Note: The size of the executable in bytes"); xml?.WriteString(o.Size); xml?.WriteEndElement(); xml?.WriteStartElement("Hash"); xml?.WriteAttributeString("title", "Note: The calculated hash for the pf file that should match the hash in the source file name"); xml?.WriteString(o.Hash); xml?.WriteEndElement(); xml?.WriteStartElement("Version"); xml?.WriteAttributeString("title", "Note: The operating system that generated the prefetch file"); xml?.WriteString(o.Version); xml?.WriteEndElement(); xml?.WriteElementString("Note", o.Note); xml?.WriteElementString("Volume0Name", o.Volume0Name); xml?.WriteElementString("Volume0Serial", o.Volume0Serial); xml?.WriteElementString("Volume0Created", o.Volume0Created); xml?.WriteElementString("Volume1Name", o.Volume1Name); xml?.WriteElementString("Volume1Serial", o.Volume1Serial); xml?.WriteElementString("Volume1Created", o.Volume1Created); xml?.WriteStartElement("Directories"); xml?.WriteAttributeString("title", "A comma separated list of all directories accessed by the executable"); xml?.WriteString(o.Directories); xml?.WriteEndElement(); xml?.WriteStartElement("FilesLoaded"); xml?.WriteAttributeString("title", "A comma separated list of all files that were loaded by the executable"); xml?.WriteString(o.FilesLoaded); xml?.WriteEndElement(); xml?.WriteEndElement(); } //Close CSV stuff streamWriter?.Flush(); streamWriter?.Close(); streamWriterTl?.Flush(); streamWriterTl?.Close(); //Close XML xml?.WriteEndElement(); xml?.WriteEndDocument(); xml?.Flush(); } } catch (Exception ex) { _logger.Error($"Error exporting data! Error: {ex.Message}"); } } }