- work in progress
- added measurement method to measure search speed - added new search implementation using Parallel.ForEach
This commit is contained in:
parent
2a81943af1
commit
365848d9a1
@ -590,7 +590,7 @@ namespace winPEAS
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
if (!string.IsNullOrEmpty(pathname))
|
||||
{
|
||||
FileVersionInfo info = FileVersionInfo.GetVersionInfo(pathname.ToString());
|
||||
if (!ignore_company.IsMatch(info.CompanyName))
|
||||
@ -598,10 +598,6 @@ namespace winPEAS
|
||||
results[pathname] = info;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Beaprint.GrayPrint("Error: " + ex);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
@ -0,0 +1,142 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FastSearchLibrary
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Represents a class for fast file search.
|
||||
/// </summary>
|
||||
public class FileSearcher
|
||||
{
|
||||
static public List<FileInfo> GetFilesFast(string folder, string pattern = "*", HashSet<string> excludedDirs = null)
|
||||
{
|
||||
ConcurrentBag<FileInfo> files = new ConcurrentBag<FileInfo>();
|
||||
|
||||
List<DirectoryInfo> startDirs = GetStartDirectories(folder, files, pattern, excludedDirs);
|
||||
|
||||
//startDirs.AsParallel().ForAll((d) =>
|
||||
//{
|
||||
// GetStartDirectories(d.FullName, files, pattern).AsParallel().ForAll((dir) =>
|
||||
// {
|
||||
// GetFiles(dir.FullName, pattern).ForEach((f) => files.Add(f));
|
||||
// });
|
||||
//});
|
||||
|
||||
Parallel.ForEach(startDirs, (d) =>
|
||||
{
|
||||
Parallel.ForEach(GetStartDirectories(d.FullName, files, pattern, excludedDirs), (dir) =>
|
||||
{
|
||||
GetFiles(dir.FullName, pattern).ForEach((f) => files.Add(f));
|
||||
});
|
||||
});
|
||||
|
||||
return files.ToList();
|
||||
}
|
||||
|
||||
static private List<DirectoryInfo> GetStartDirectories(
|
||||
string folder,
|
||||
ConcurrentBag<FileInfo> files,
|
||||
string pattern,
|
||||
HashSet<string> excludedDirs = null)
|
||||
{
|
||||
DirectoryInfo[] directories;
|
||||
|
||||
if (excludedDirs != null)
|
||||
{
|
||||
foreach (var excludedDir in excludedDirs)
|
||||
{
|
||||
if (folder.Contains(excludedDir))
|
||||
{
|
||||
return new List<DirectoryInfo>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
DirectoryInfo dirInfo = new DirectoryInfo(folder);
|
||||
directories = dirInfo.GetDirectories();
|
||||
|
||||
foreach (var f in dirInfo.GetFiles(pattern))
|
||||
{
|
||||
files.Add(f);
|
||||
}
|
||||
|
||||
if (directories.Length > 1)
|
||||
return new List<DirectoryInfo>(directories);
|
||||
|
||||
if (directories.Length == 0)
|
||||
return new List<DirectoryInfo>();
|
||||
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
return new List<DirectoryInfo>();
|
||||
}
|
||||
catch (PathTooLongException ex)
|
||||
{
|
||||
return new List<DirectoryInfo>();
|
||||
}
|
||||
catch (DirectoryNotFoundException ex)
|
||||
{
|
||||
return new List<DirectoryInfo>();
|
||||
}
|
||||
|
||||
return GetStartDirectories(directories[0].FullName, files, pattern);
|
||||
}
|
||||
|
||||
static public List<FileInfo> GetFiles(string folder, string pattern = "*")
|
||||
{
|
||||
DirectoryInfo dirInfo;
|
||||
DirectoryInfo[] directories;
|
||||
try
|
||||
{
|
||||
dirInfo = new DirectoryInfo(folder);
|
||||
directories = dirInfo.GetDirectories();
|
||||
|
||||
if (directories.Length == 0)
|
||||
return new List<FileInfo>(dirInfo.GetFiles(pattern));
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
return new List<FileInfo>();
|
||||
}
|
||||
catch (PathTooLongException ex)
|
||||
{
|
||||
return new List<FileInfo>();
|
||||
}
|
||||
catch (DirectoryNotFoundException ex)
|
||||
{
|
||||
return new List<FileInfo>();
|
||||
}
|
||||
|
||||
List<FileInfo> result = new List<FileInfo>();
|
||||
|
||||
foreach (var d in directories)
|
||||
{
|
||||
result.AddRange(GetFiles(d.FullName, pattern));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
result.AddRange(dirInfo.GetFiles(pattern));
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
}
|
||||
catch (PathTooLongException ex)
|
||||
{
|
||||
}
|
||||
catch (DirectoryNotFoundException ex)
|
||||
{
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
@ -5,16 +5,16 @@ using System.IO;
|
||||
using Microsoft.Win32;
|
||||
using System.Security.Principal;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Reflection;
|
||||
using System.Security.AccessControl;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using FastSearchLibrary;
|
||||
|
||||
namespace winPEAS
|
||||
{
|
||||
class MyUtils
|
||||
public class MyUtils
|
||||
{
|
||||
//////////////////////
|
||||
/// IsDomainJoined ///
|
||||
@ -598,7 +598,7 @@ namespace winPEAS
|
||||
return false;
|
||||
}
|
||||
|
||||
public static List<string> FindFiles(string path, string patterns)
|
||||
public static List<string> FindFiles_old_implementation(string path, string patterns)
|
||||
{
|
||||
// finds files matching one or more patterns under a given path, recursive
|
||||
// adapted from http://csharphelper.com/blog/2015/06/find-files-that-match-multiple-patterns-in-c/
|
||||
@ -606,6 +606,11 @@ namespace winPEAS
|
||||
|
||||
var files = new List<string>();
|
||||
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
return files;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// search every pattern in this directory's files
|
||||
@ -616,22 +621,78 @@ namespace winPEAS
|
||||
|
||||
// go recurse in all sub-directories
|
||||
foreach (var directory in Directory.GetDirectories(path))
|
||||
files.AddRange(FindFiles(directory, patterns));
|
||||
files.AddRange(FindFiles_old_implementation(directory, patterns));
|
||||
}
|
||||
catch (UnauthorizedAccessException) { }
|
||||
catch (PathTooLongException) { }
|
||||
catch (DirectoryNotFoundException) { }
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
public static void FindFiles(string path, string patterns, Dictionary<string, string> color)
|
||||
public static List<string> FindFiles_fileSearcher(string path, string patterns)
|
||||
{
|
||||
var files = new List<string>();
|
||||
|
||||
foreach (string pattern in patterns.Split(';'))
|
||||
{
|
||||
// var found = Directory.GetFiles(path, pattern, SearchOption.AllDirectories);
|
||||
List<FileInfo> res = FileSearcher.GetFilesFast(path, pattern);
|
||||
files.AddRange(res.Select(s => s.FullName));
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
private static void MeasureMethod(Action action, string description = null)
|
||||
{
|
||||
var timer = new Stopwatch();
|
||||
timer.Start();
|
||||
action();
|
||||
timer.Stop();
|
||||
|
||||
TimeSpan timeTaken = timer.Elapsed;
|
||||
string log = $"({description ?? string.Empty}) Time taken: " + timeTaken.ToString(@"m\:ss\.fff");
|
||||
Beaprint.LinkPrint(log);
|
||||
}
|
||||
|
||||
private static void PrintSearchResults(IEnumerable<string> results, string description = null)
|
||||
{
|
||||
Beaprint.LinkPrint($"------------------------- results: {description ?? string.Empty} --------------------------------");
|
||||
if (results != null)
|
||||
{
|
||||
Beaprint.LinkPrint(string.Join("\n", results ?? Enumerable.Empty<string>()));
|
||||
}
|
||||
Beaprint.LinkPrint($"------------------------- results: {description ?? string.Empty} --------------------------------");
|
||||
Beaprint.LinkPrint("\n\n\n\n");
|
||||
}
|
||||
|
||||
public static List<string> FindFiles(string path, string patterns)
|
||||
{
|
||||
List<string> result = new List<string>();
|
||||
|
||||
MeasureMethod(() => result = FindFiles_old_implementation(path, patterns), "old implementation");
|
||||
PrintSearchResults(result, "old implementation");
|
||||
|
||||
MeasureMethod(() => result = FindFiles_fileSearcher(path, patterns), "new implementation");
|
||||
PrintSearchResults(result, "new implementation");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void FindFiles_old_implementation(string path, string patterns, Dictionary<string, string> color)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// search every pattern in this directory's files
|
||||
foreach (string pattern in patterns.Split(';'))
|
||||
{
|
||||
Beaprint.AnsiPrint(" "+String.Join("\n ", Directory.GetFiles(path, pattern, SearchOption.TopDirectoryOnly).Where(filepath => !filepath.Contains(".dll"))), color);
|
||||
Beaprint.AnsiPrint(" " + String.Join("\n ", Directory.GetFiles(path, pattern, SearchOption.TopDirectoryOnly).Where(filepath => !filepath.Contains(".dll"))), color);
|
||||
}
|
||||
|
||||
if (!Program.search_fast)
|
||||
@ -641,13 +702,37 @@ namespace winPEAS
|
||||
foreach (string directory in Directory.GetDirectories(path))
|
||||
{
|
||||
if (!directory.Contains("AppData"))
|
||||
FindFiles(directory, patterns, color);
|
||||
FindFiles_old_implementation(directory, patterns, color);
|
||||
}
|
||||
}
|
||||
catch (UnauthorizedAccessException) { }
|
||||
catch (PathTooLongException) { }
|
||||
catch (DirectoryNotFoundException) { }
|
||||
}
|
||||
|
||||
public static void FindFiles_fileSearcher(string path, string patterns, Dictionary<string, string> color, HashSet<string> excludedDirs = null)
|
||||
{
|
||||
// search every pattern in this directory's files
|
||||
foreach (string pattern in patterns.Split(';'))
|
||||
{
|
||||
// var found = Directory.GetFiles(path, pattern, SearchOption.TopDirectoryOnly).Where(filepath => !filepath.Contains(".dll"));
|
||||
List<FileInfo> res = FileSearcher.GetFilesFast(path, pattern, excludedDirs);
|
||||
var found = res.Where(filepath => filepath.Extension != null && !filepath.Extension.Equals("dll")).Select(s => s.FullName);
|
||||
Beaprint.AnsiPrint(" " + String.Join("\n ", found), color);
|
||||
}
|
||||
}
|
||||
|
||||
public static void FindFiles(string path, string patterns, Dictionary<string, string> color)
|
||||
{
|
||||
Beaprint.LinkPrint($"------------------------- results: old implementation --------------------------------");
|
||||
MeasureMethod(() => FindFiles_old_implementation(path, patterns, color), "old implementation");
|
||||
Beaprint.LinkPrint($"------------------------- results: old implementation --------------------------------");
|
||||
Beaprint.LinkPrint("\n\n\n\n");
|
||||
Beaprint.LinkPrint($"------------------------- results: new implementation --------------------------------");
|
||||
HashSet<string> excludedDirs = new HashSet<string>() { "AppData" };
|
||||
MeasureMethod(() => FindFiles_fileSearcher(path, patterns, color, excludedDirs), "new implementation");
|
||||
Beaprint.LinkPrint($"------------------------- results: new implementation --------------------------------");
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
//////// MISC ////////
|
||||
|
@ -87,6 +87,9 @@
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<StartupObject>winPEAS.Program</StartupObject>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
@ -104,6 +107,7 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="ApplicationInfo.cs" />
|
||||
<Compile Include="Beaprint.cs" />
|
||||
<Compile Include="FastSearch\FileSearcher\FileSearcher.cs" />
|
||||
<Compile Include="InterestingFiles.cs" />
|
||||
<Compile Include="KnownFileCredsInfo.cs" />
|
||||
<Compile Include="MyUtils.cs" />
|
||||
@ -173,5 +177,6 @@
|
||||
<EmbeddedResource Include="Properties\Resources.ru.resx" />
|
||||
<EmbeddedResource Include="Properties\Resources.zh-CN.resx" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
Loading…
Reference in New Issue
Block a user