Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
195 changes: 151 additions & 44 deletions RECmd/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ private static async Task Main(string[] args)

new Option<string>(
"--csv",
"Directory to save CSV formatted results to. Required when -bn is used"),
"Directory to save CSV formatted results to"),
Comment thread
AndrewRathbun marked this conversation as resolved.

new Option<string>(
"--csvf",
Expand Down Expand Up @@ -342,6 +342,13 @@ private static void DoWork(string d, string f, string kn, string vn, string bn,

ActiveDateTimeFormat = dt;

ServiceStack.Text.JsConfig<DateTimeOffset?>.SerializeFn = time => time?.ToString(dt, CultureInfo.InvariantCulture);
ServiceStack.Text.JsConfig<DateTimeOffset>.SerializeFn = time => time.ToString(dt, CultureInfo.InvariantCulture);
ServiceStack.Text.JsConfig<DateTime?>.SerializeFn = time => time?.ToString(dt, CultureInfo.InvariantCulture);
ServiceStack.Text.JsConfig<DateTime>.SerializeFn = time => time.ToString(dt, CultureInfo.InvariantCulture);
ServiceStack.Text.JsConfig.IncludeNullValues = true;
ServiceStack.Text.JsConfig.IncludeNullValuesInDictionaries = true;

var formatter =
new DateTimeOffsetFormatter(CultureInfo.CurrentCulture);

Expand Down Expand Up @@ -428,9 +435,15 @@ private static void DoWork(string d, string f, string kn, string vn, string bn,
return;
}

if (csv.IsNullOrEmpty())
if (csv.IsNullOrEmpty() && json.IsNullOrEmpty())
{
Log.Error("Either {S1} or {S2} is required when using {S3}. Exiting","--csv","--json","--bn");
return;
}

if (csv.IsNullOrEmpty() == false && json.IsNullOrEmpty() == false)
{
Log.Error("{S1} is required when using {S2}. Exiting","--csv","--bn");
Log.Error("Only use one of {S1} or {S2} when using {S3}. Exiting", "--csv", "--json", "--bn");
return;
}

Comment thread
AndrewRathbun marked this conversation as resolved.
Expand Down Expand Up @@ -1596,7 +1609,7 @@ private static void DoWork(string d, string f, string kn, string vn, string bn,
} //end min size option
else if (bn?.Length > 0) //batch mode
{
ProcessBatch(reBatch, reg, d, f, csv, csvf, dt);
ProcessBatch(reBatch, reg, d, f, csv, csvf, json, jsonf, dt);
}
}
catch (Exception ex)
Expand Down Expand Up @@ -1637,43 +1650,77 @@ private static void DoWork(string d, string f, string kn, string vn, string bn,
Log.Information("Total search time: {TotalSeconds:N3} seconds",totalSeconds);
if (_batchCsvOutList.Count > 0)
{
if (Directory.Exists(csv) == false)
if (csv.IsNullOrEmpty() == false)
{
Log.Information(
"Path to {Csv} doesn't exist. Creating...",csv);
Directory.CreateDirectory(csv);
}
if (Directory.Exists(csv) == false)
{
Log.Information(
"Path to {Csv} doesn't exist. Creating...", csv);
Directory.CreateDirectory(csv);
}

var outName =
$"{RunTimestamp}_RECmd_Batch_{Path.GetFileNameWithoutExtension(bn)}_Output.csv";
var outName =
$"{RunTimestamp}_RECmd_Batch_{Path.GetFileNameWithoutExtension(bn)}_Output.csv";

if (csvf.IsNullOrEmpty() == false)
{
outName = Path.GetFileName(csvf);
}
if (csvf.IsNullOrEmpty() == false)
{
outName = Path.GetFileName(csvf);
}

var outFile = Path.Combine(csv, outName);
var outFile = Path.Combine(csv, outName);

Console.WriteLine();
Log.Information("Saving batch mode CSV file to {OutFile}",outFile);
Console.WriteLine();
Log.Information("Saving batch mode CSV file to {OutFile}", outFile);

var swCsv = new StreamWriter(outFile, false, Encoding.UTF8);
var csvWriter = new CsvWriter(swCsv, CultureInfo.InvariantCulture);
var swCsv = new StreamWriter(outFile, false, Encoding.UTF8);
var csvWriter = new CsvWriter(swCsv, CultureInfo.InvariantCulture);

var foo = csvWriter.Context.AutoMap<BatchCsvOut>();
var foo = csvWriter.Context.AutoMap<BatchCsvOut>();

foo.Map(t => t.LastWriteTimestamp).Convert(t =>
$"{t.Value.LastWriteTimestamp?.ToString(dt)}");
foo.Map(t => t.LastWriteTimestamp).Convert(t =>
$"{t.Value.LastWriteTimestamp?.ToString(dt)}");

csvWriter.Context.RegisterClassMap(foo);
csvWriter.Context.RegisterClassMap(foo);

csvWriter.WriteHeader<BatchCsvOut>();
csvWriter.NextRecord();
csvWriter.WriteHeader<BatchCsvOut>();
csvWriter.NextRecord();

csvWriter.WriteRecords(_batchCsvOutList);
csvWriter.WriteRecords(_batchCsvOutList);

swCsv.Flush();
swCsv.Close();
}

swCsv.Flush();
swCsv.Close();
if (json.IsNullOrEmpty() == false)
{
if (Directory.Exists(json) == false)
{
Log.Information(
"Path to {Json} doesn't exist. Creating...",json);
Directory.CreateDirectory(json);
}

var outName =
$"{RunTimestamp}_RECmd_Batch_{Path.GetFileNameWithoutExtension(bn)}_Output.json";

if (jsonf.IsNullOrEmpty() == false)
{
outName = Path.GetFileName(jsonf);
}

var outFile = Path.Combine(json, outName);

Console.WriteLine();
Log.Information("Saving batch mode JSON file to {OutFile}",outFile);

using (var writer = new StreamWriter(outFile, false, Encoding.UTF8))
{
foreach (var item in _batchCsvOutList)
{
writer.WriteLine(item.ToJson());
}
}
}
}
}

Expand Down Expand Up @@ -1841,7 +1888,7 @@ private static void UpdateFromRepo()
Directory.Delete(Path.Combine(BaseDirectory, "RECmd-master"), true);
}

private static void ProcessBatchKey(RegistryKey key, Key batchKey, string hivePath, string d, string f, string csv, string csvf, string dt)
private static void ProcessBatchKey(RegistryKey key, Key batchKey, string hivePath, string d, string f, string csv, string csvf, string json, string jsonf, string dt)
{
var regKey = key;

Expand All @@ -1859,15 +1906,15 @@ private static void ProcessBatchKey(RegistryKey key, Key batchKey, string hivePa
if (regVal != null)
{
Log.Verbose("Found value {ValueName} in key {KeyPath}!",batchKey.ValueName,regKey.KeyPath);
BatchDumpKey(key, batchKey, hivePath, d, f, csv, csvf, dt);
BatchDumpKey(key, batchKey, hivePath, d, f, csv, csvf, json, jsonf, dt);
}
}

if (regVal == null && batchKey.ValueName.IsNullOrEmpty())
{
//do not need to find a value,
Log.Verbose("Found key {KeyPath}!",key.KeyPath);
BatchDumpKey(key, batchKey, hivePath, d, f, csv, csvf, dt);
BatchDumpKey(key, batchKey, hivePath, d, f, csv, csvf, json, jsonf, dt);
}


Expand All @@ -1878,11 +1925,11 @@ private static void ProcessBatchKey(RegistryKey key, Key batchKey, string hivePa

foreach (var regKeySubKey in regKey.SubKeys)
{
ProcessBatchKey(regKeySubKey, batchKey, hivePath, d, f, csv, csvf, dt);
ProcessBatchKey(regKeySubKey, batchKey, hivePath, d, f, csv, csvf, json, jsonf, dt);
}
}

private static void ProcessBatch(ReBatch reBatch, RegistryHive regHive, string d, string f, string csv, string csvf, string dt)
private static void ProcessBatch(ReBatch reBatch, RegistryHive regHive, string d, string f, string csv, string csvf, string json, string jsonf, string dt)
{
foreach (var key in reBatch.Keys)
{
Expand All @@ -1906,7 +1953,7 @@ private static void ProcessBatch(ReBatch reBatch, RegistryHive regHive, string d
continue;
}

ProcessBatchKey(regKey, key, regHive.HivePath, d, f, csv, csvf, dt);
ProcessBatchKey(regKey, key, regHive.HivePath, d, f, csv, csvf, json, jsonf, dt);
}
else if (key.KeyPath.Contains("*"))
{
Expand Down Expand Up @@ -1952,7 +1999,7 @@ private static void ProcessBatch(ReBatch reBatch, RegistryHive regHive, string d
//BatchDumpKey(regKey, key, regHive.HivePath);

//switch to this for better recursive support vs BatchDumpKey
ProcessBatchKey(regKey, key, regHive.HivePath, d, f, csv, csvf, dt);
ProcessBatchKey(regKey, key, regHive.HivePath, d, f, csv, csvf, json, jsonf, dt);
}
}
else
Expand All @@ -1965,7 +2012,7 @@ private static void ProcessBatch(ReBatch reBatch, RegistryHive regHive, string d
continue;
}

ProcessBatchKey(regKey, key, regHive.HivePath, d, f, csv, csvf, dt);
ProcessBatchKey(regKey, key, regHive.HivePath, d, f, csv, csvf, json, jsonf, dt);
}
}
}
Expand Down Expand Up @@ -2044,7 +2091,7 @@ private static List<IRegistryPluginBase> GetPluginsToActivate(RegistryKey regKey
return pluginsToActivate;
}

private static void BatchDumpKey(RegistryKey regKey, Key key, string hivePath, string d, string f, string csv, string csvf, string dt)
private static void BatchDumpKey(RegistryKey regKey, Key key, string hivePath, string d, string f, string csv, string csvf, string json, string jsonf, string dt)
{
Log.Verbose("Batch dumping {KeyPath} in {HivePath}",regKey.KeyPath,hivePath);

Expand All @@ -2066,7 +2113,7 @@ private static void BatchDumpKey(RegistryKey regKey, Key key, string hivePath, s

pig.ProcessValues(regKey);

var pluginDetailsFile = DumpPluginValues(pig, hivePath, d, f, csv, csvf);
var pluginDetailsFile = DumpPluginValues(pig, hivePath, d, f, csv, csvf, json, jsonf);

var path = hivePath;

Expand Down Expand Up @@ -2144,7 +2191,7 @@ private static void BatchDumpKey(RegistryKey regKey, Key key, string hivePath, s
}
}

private static string DumpPluginValues(IRegistryPluginGrid plugin, string hivePath, string d, string f, string csv, string csvf)
private static string DumpPluginValues(IRegistryPluginGrid plugin, string hivePath, string d, string f, string csv, string csvf, string json, string jsonf)
{
var pluginType = plugin.GetType();

Expand All @@ -2169,28 +2216,88 @@ private static string DumpPluginValues(IRegistryPluginGrid plugin, string hivePa

var outbase = $"{RunTimestamp}_{pluginType.Name}_{hiveName1}.csv";

if (Directory.Exists(csv) == false)
if (csv.IsNullOrEmpty() == false && Directory.Exists(csv) == false)
{
Log.Information(
"Path to {Csv} doesn't exist. Creating...",csv);
Directory.CreateDirectory(csv);
}

if (json.IsNullOrEmpty() == false && Directory.Exists(json) == false)
{
Log.Information(
"Path to {json} doesn't exist. Creating...",json);
Directory.CreateDirectory(json);
}

if (csvf.IsNullOrEmpty() == false)
{
outbase =
$"{Path.GetFileNameWithoutExtension(csvf)}_{pluginType.Name}{Path.GetExtension(csvf)}";
}

var outFile = Path.Combine(csv, RunTimestamp, outbase);
string outputDir = null;
if (json.IsNullOrEmpty() == false)
{
outputDir = json;
}
else if (csv.IsNullOrEmpty() == false)
{
outputDir = csv;
}
else
{
return null;
}

if (Directory.Exists(Path.GetDirectoryName(outFile)) == false)
var outFile = Path.Combine(outputDir, RunTimestamp, outbase);
var outDir = Path.GetDirectoryName(outFile);
if (!string.IsNullOrEmpty(outDir) && !Directory.Exists(outDir))
{
Directory.CreateDirectory(Path.GetDirectoryName(outFile));
Directory.CreateDirectory(outDir);
}

var exists = File.Exists(outFile);

if (json.IsNullOrEmpty() == false)
{
outbase = $"{RunTimestamp}_{pluginType.Name}_{hiveName1}.json";
if (jsonf.IsNullOrEmpty() == false)
{
outbase =
$"{Path.GetFileNameWithoutExtension(jsonf)}_{pluginType.Name}{Path.GetExtension(jsonf)}";
Comment thread
AndrewRathbun marked this conversation as resolved.
}

outFile = Path.Combine(outputDir, RunTimestamp, outbase);

using (var writer = new StreamWriter(outFile, true, Encoding.UTF8))
{
if (plugin.Values.Count > 0)
{
var propsToExclude = plugin.Values[0].GetType().GetProperties()
.Where(p => p.Name.StartsWith("BatchValueData"))
.Select(p => p.Name)
.ToList();
Comment thread
AndrewRathbun marked this conversation as resolved.

foreach (var item in plugin.Values)
{
var dict = new Dictionary<string, object>();
foreach (var prop in item.GetType().GetProperties())
{
if (propsToExclude.Contains(prop.Name) == false)
{
dict.Add(prop.Name, prop.GetValue(item));
}
}
writer.WriteLine(dict.ToJson());
}
}
}

return outFile;
}


using var sw = new StreamWriter(outFile, true, Encoding.UTF8);
var csvWriter = new CsvWriter(sw, CultureInfo.InvariantCulture);

Expand Down
Loading