From 1b1bb58830b770bce67b07aff13aad7fd874b685 Mon Sep 17 00:00:00 2001 From: RandomCrocodile Date: Sun, 7 Jun 2026 18:44:04 +0200 Subject: [PATCH] feat(core): add wildcard module loading in .crproj (upstream #481) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cherry-pick of mkaring/ConfuserEx#481 — allows using wildcards like *.dll in module paths to batch-load modules from the base directory. The Load method now accepts an optional baseDirRoot parameter to resolve relative base directory paths. New internal helpers AddModule, IsWildcard, and BatchLoadModules handle wildcard expansion using Directory.GetFiles with TopDirectoryOnly search. --- Confuser.CLI/Program.cs | 6 ++-- Confuser.Core/Project/ConfuserProject.cs | 45 +++++++++++++++++++++--- 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/Confuser.CLI/Program.cs b/Confuser.CLI/Program.cs index 267d82d0d..d8c56421e 100644 --- a/Confuser.CLI/Program.cs +++ b/Confuser.CLI/Program.cs @@ -60,10 +60,8 @@ static int Main(string[] args) { try { var xmlDoc = new XmlDocument(); xmlDoc.Load(files[0]); - proj.Load(xmlDoc); - string crprojDir = Path.GetDirectoryName(Path.GetFullPath(files[0])); - proj.BaseDirectory = Path.GetFullPath(Path.Combine(crprojDir, proj.BaseDirectory)); - proj.OutputDirectory = Path.GetFullPath(Path.Combine(crprojDir, proj.OutputDirectory)); + proj.Load(xmlDoc, Path.GetDirectoryName(Path.GetFullPath(files[0]))); + proj.OutputDirectory = Path.GetFullPath(Path.Combine(proj.BaseDirectory, proj.OutputDirectory)); } catch (Exception ex) { WriteLineWithColor(ConsoleColor.Red, "Failed to load project:"); diff --git a/Confuser.Core/Project/ConfuserProject.cs b/Confuser.Core/Project/ConfuserProject.cs index d8dc25a54..6f0073637 100644 --- a/Confuser.Core/Project/ConfuserProject.cs +++ b/Confuser.Core/Project/ConfuserProject.cs @@ -626,7 +626,7 @@ public XmlDocument Save() { /// /// The project XML contains schema errors. /// - public void Load(XmlDocument doc) { + public void Load(XmlDocument doc, string baseDirRoot = null) { doc.Schemas.Add(Schema); var exceptions = new List(); doc.Validate((sender, e) => { @@ -641,6 +641,10 @@ public void Load(XmlDocument doc) { OutputDirectory = docElem.Attributes["outputDir"].Value; BaseDirectory = docElem.Attributes["baseDir"].Value; + if (!string.IsNullOrEmpty(baseDirRoot)) + { + BaseDirectory = Path.Combine(baseDirRoot, BaseDirectory); + } if (docElem.Attributes["seed"] != null) Seed = docElem.Attributes["seed"].Value.NullIfEmpty(); @@ -674,13 +678,46 @@ public void Load(XmlDocument doc) { PluginPaths.Add(i.InnerText); } else { - var asm = new ProjectModule(); - asm.Load(i); - Add(asm); + AddModule(i); } } } + internal void AddModule(XmlElement elem) { + if (IsWildcard(elem.Attributes["path"].Value)) { + BatchLoadModules(elem); + } + else { + var asm = new ProjectModule(); + asm.Load(elem); + Add(asm); + } + } + + internal bool IsWildcard(string path) { + return !string.IsNullOrEmpty(path) && path.Contains(@"*"); + } + + internal bool BatchLoadModules(XmlElement elem) { + string wildCardPath = elem.Attributes["path"].Value; + string[] files = Directory.GetFiles(BaseDirectory, wildCardPath, SearchOption.TopDirectoryOnly); + if (files.Length <= 0) + { + return false; + } + + var asmPrototype = new ProjectModule(); + asmPrototype.Load(elem); + + foreach (string fileName in files) { + var moduleEntry = asmPrototype.Clone(); + moduleEntry.Path = fileName; + Add(moduleEntry); + } + + return true; + } + /// /// Clones this instance. ///