From 499f40f92fcded1c4dbcabfd8f34e624305ff687 Mon Sep 17 00:00:00 2001 From: Christoph Date: Tue, 5 Nov 2024 18:07:52 +0100 Subject: [PATCH] Write files in windowsPE pass more efficiently #99 --- Extensions.cs | 10 +++++++ Main.cs | 61 ++++++++++++++++++++++++++++++++------- modifier/Disk.cs | 13 +++------ modifier/Optimizations.cs | 13 +++------ 4 files changed, 68 insertions(+), 29 deletions(-) diff --git a/Extensions.cs b/Extensions.cs index c799db0..764edee 100644 --- a/Extensions.cs +++ b/Extensions.cs @@ -46,4 +46,14 @@ public static IImmutableDictionary ToKeyedDictionary(this IEnumera keyComparer: StringComparer.OrdinalIgnoreCase ); } + + public static string JoinString(this IEnumerable enumerable, string separator) + { + return string.Join(separator, enumerable); + } + + public static string JoinString(this IEnumerable enumerable, char separator) + { + return string.Join(separator, enumerable); + } } \ No newline at end of file diff --git a/Main.cs b/Main.cs index 239a85b..ee1f0e0 100644 --- a/Main.cs +++ b/Main.cs @@ -217,8 +217,43 @@ public static string InvokeJScript(string filepath) return @$"cscript.exe //E:jscript ""{filepath}"""; } - public static IEnumerable WriteToFile(string path, string line) + public static List WriteToFile(string path, IEnumerable lines) { + static IEnumerable Trim(IEnumerable input) + { + return input + .Select(l => l.Trim()) + .Where(e => e.Length > 0); + } + + static IEnumerable> Join(IEnumerable input) + { + int max = 200; + List> output = []; + List current = []; + foreach (string line in input) + { + if (current.Count == 0) + { + current.Add(line); + } + else if (current.Sum(e => e.Length + 10) + line.Length > max) + { + output.Add(current); + current = [line]; + } + else + { + current.Add(line); + } + } + if (current.Count > 0) + { + output.Add(current); + } + return output; + } + static string EscapeShell(string command) { return command @@ -227,20 +262,24 @@ static string EscapeShell(string command) .Replace("<", "^<") .Replace(">", "^>") .Replace("|", "^|") - .Replace("%", "^%"); + .Replace("%", "^%") + .Replace(")", "^)"); } - if (string.IsNullOrWhiteSpace(line)) + IEnumerable Enumerate() { - yield break; - } - - string command = $@"cmd.exe /c "">>""{path}"" echo {EscapeShell(line)}"""; - if (command.Length >= 255) - { - throw new ConfigurationException($"Line '{line}' is too long."); + foreach (IEnumerable group in Join(Trim(lines))) + { + string echos = group.Select(l => $"echo {EscapeShell(l)}").JoinString('&'); + string command = $@"cmd.exe /c "">>""{path}"" ({echos})"""; + if (command.Length >= 255) + { + throw new ConfigurationException($"Line '{command}' is too long."); + } + yield return command; + } } - yield return command; + return Enumerate().ToList(); } } diff --git a/modifier/Disk.cs b/modifier/Disk.cs index dab7d94..221f552 100644 --- a/modifier/Disk.cs +++ b/modifier/Disk.cs @@ -132,15 +132,10 @@ private void WriteScript(IEnumerable lines) string log = @"X:\diskpart.log"; CommandAppender appender = GetAppender(CommandConfig.WindowsPE); - foreach (string line in lines) - { - appender.Append( - CommandBuilder.WriteToFile(script, line) - ); - } - appender.Append( - CommandBuilder.ShellCommand($@"diskpart.exe /s ""{script}"" >>""{log}"" || ( type ""{log}"" & echo diskpart encountered an error. & pause & exit /b 1 )") - ); + appender.Append([ + ..CommandBuilder.WriteToFile(script, lines), + CommandBuilder.ShellCommand($@"diskpart.exe /s ""{script}"" >>""{log}"" || ( type ""{log}"" & echo diskpart encountered an error. & pause & exit /b 1 )"), + ]); } public static string GetCustomDiskpartScript() diff --git a/modifier/Optimizations.cs b/modifier/Optimizations.cs index 90e258d..1c0e5af 100644 --- a/modifier/Optimizations.cs +++ b/modifier/Optimizations.cs @@ -146,16 +146,11 @@ IEnumerable SetExplorerOptions(string rootKey, string subKey) if (Configuration.DisableDefender) { CommandAppender pe = GetAppender(CommandConfig.WindowsPE); - const string path = @"X:\disable-defender.vbs"; - foreach (string line in Util.SplitLines(Util.StringFromResource("disable-defender.vbs"))) - { - pe.Append( - CommandBuilder.WriteToFile(path, line) - ); - } - pe.Append( + const string path = @"X:\defender.vbs"; + pe.Append([ + ..CommandBuilder.WriteToFile(path, Util.SplitLines(Util.StringFromResource("disable-defender.vbs"))), CommandBuilder.ShellCommand($"start /MIN cscript.exe //E:vbscript {path}") - ); + ]); } if (Configuration.DisableSac)