From b4ab0036f019887d5ef15a41c01df0c557218640 Mon Sep 17 00:00:00 2001 From: Katy Coe Date: Sun, 19 Jan 2020 04:03:14 +0100 Subject: [PATCH] CLI/Output: Add option to create Visual Studio solution (.sln) (no project files yet) --- Il2CppDumper/Il2CppCSharpDumper.cs | 42 ++++- Il2CppDumper/Il2CppDumper.csproj | 15 ++ Il2CppDumper/Program.cs | 8 + Il2CppDumper/Properties/Resources.Designer.cs | 108 +++++++++++++ Il2CppDumper/Properties/Resources.resx | 150 ++++++++++++++++++ 5 files changed, 322 insertions(+), 1 deletion(-) create mode 100644 Il2CppDumper/Properties/Resources.Designer.cs create mode 100644 Il2CppDumper/Properties/Resources.resx diff --git a/Il2CppDumper/Il2CppCSharpDumper.cs b/Il2CppDumper/Il2CppCSharpDumper.cs index 006f6e4..6fe9a21 100644 --- a/Il2CppDumper/Il2CppCSharpDumper.cs +++ b/Il2CppDumper/Il2CppCSharpDumper.cs @@ -3,12 +3,14 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; +using Il2CppDumper.Properties; using Il2CppInspector.Reflection; using Assembly = Il2CppInspector.Reflection.Assembly; using CustomAttributeData = Il2CppInspector.Reflection.CustomAttributeData; @@ -75,7 +77,7 @@ namespace Il2CppInspector }); } - public void WriteFilesByClassTree(string outPath, bool separateAttributes) { + public HashSet WriteFilesByClassTree(string outPath, bool separateAttributes) { usedAssemblyAttributes.Clear(); var usedAssemblies = new HashSet(); @@ -94,6 +96,44 @@ namespace Il2CppInspector if (separateAttributes && usedAssemblies.Any()) foreach (var asm in usedAssemblies) File.WriteAllText($"{outPath}\\{asm.ShortName.Replace(".dll", "")}\\AssemblyInfo.cs", generateAssemblyInfo(new [] {asm})); + + return usedAssemblies; + } + + // Create a Visual Studio solution + public void WriteSolution(string outPath) { + // Required settings + MustCompile = true; + + // Output source files in tree format with separate assembly attributes + var assemblies = WriteFilesByClassTree(outPath, true); + + // Per-project (per-assembly) solution definition and configuration + var slnProjectDefs = new StringBuilder(); + var slnProjectConfigs = new StringBuilder(); + + foreach (var asm in assemblies) { + var guid = Guid.NewGuid(); + var name = asm.ShortName.Replace(".dll", ""); + var def = Resources.SlnProjectDefinition + .Replace("%PROJECTGUID%", guid.ToString()) + .Replace("%PROJECTNAME%", name) + .Replace("%CSPROJRELATIVEPATH%", $"{name}\\{name}.csproj"); + + slnProjectDefs.Append(def); + + var config = Resources.SlnProjectConfiguration + .Replace("%PROJECTGUID%", guid.ToString()); + + slnProjectConfigs.Append(config); + } + + // Merge everything into .sln file + var sln = Resources.SlnTemplate + .Replace("%PROJECTDEFINITIONS%", slnProjectDefs.ToString()) + .Replace("%PROJECTCONFIGURATIONS%", slnProjectConfigs.ToString()); + + File.WriteAllText($"{outPath}\\{Path.GetFileName(outPath)}.sln", sln); } private bool writeFile(string outFile, IEnumerable types, bool useNamespaceSyntax = true, bool outputAssemblyAttributes = true) { diff --git a/Il2CppDumper/Il2CppDumper.csproj b/Il2CppDumper/Il2CppDumper.csproj index 00050e2..bd42c48 100644 --- a/Il2CppDumper/Il2CppDumper.csproj +++ b/Il2CppDumper/Il2CppDumper.csproj @@ -26,4 +26,19 @@ + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + diff --git a/Il2CppDumper/Program.cs b/Il2CppDumper/Program.cs index 0f52620..48ea16c 100644 --- a/Il2CppDumper/Program.cs +++ b/Il2CppDumper/Program.cs @@ -56,6 +56,9 @@ namespace Il2CppInspector [Option("separate-attributes", Required = false, HelpText = "Place assembly-level attributes in their own AssemblyInfo.cs files. Only used when layout is per-assembly or tree")] public bool SeparateAssemblyAttributesFiles { get; set; } + + [Option('j', "project", Required = false, HelpText = "Create a Visual Studio solution and projects. Implies --layout tree, --must-compile and --separate-attributes")] + public bool CreateSolution { get; set; } } // Adapted from: https://stackoverflow.com/questions/16376191/measuring-code-execution-time @@ -130,6 +133,11 @@ namespace Il2CppInspector else csOut += imageSuffix; + if (options.CreateSolution) { + writer.WriteSolution(csOut); + continue; + } + switch (options.LayoutSchema.ToLower(), options.SortOrder.ToLower()) { case ("single", "index"): writer.WriteSingleFile(csOut, t => t.Index); diff --git a/Il2CppDumper/Properties/Resources.Designer.cs b/Il2CppDumper/Properties/Resources.Designer.cs new file mode 100644 index 0000000..9faf3e9 --- /dev/null +++ b/Il2CppDumper/Properties/Resources.Designer.cs @@ -0,0 +1,108 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Il2CppDumper.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Il2CppDumper.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to {%PROJECTGUID%}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + /// {%PROJECTGUID%}.Debug|Any CPU.Build.0 = Debug|Any CPU + /// {%PROJECTGUID%}.Release|Any CPU.ActiveCfg = Release|Any CPU + /// {%PROJECTGUID%}.Release|Any CPU.Build.0 = Release|Any CPU. + /// + internal static string SlnProjectConfiguration { + get { + return ResourceManager.GetString("SlnProjectConfiguration", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "%PROJECTNAME%", "%CSPROJRELATIVEPATH%", "{%PROJECTGUID%}" + ///EndProject. + /// + internal static string SlnProjectDefinition { + get { + return ResourceManager.GetString("SlnProjectDefinition", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Microsoft Visual Studio Solution File, Format Version 12.00 + ///# Visual Studio Version 16 + ///%PROJECTDEFINITIONS% + ///Global + /// GlobalSection(SolutionConfigurationPlatforms) = preSolution + /// Debug|Any CPU = Debug|Any CPU + /// Release|Any CPU = Release|Any CPU + /// EndGlobalSection + /// GlobalSection(ProjectConfigurationPlatforms) = postSolution + ///%PROJECTCONFIGURATIONS% + /// EndGlobalSection + /// GlobalSection(SolutionProperties) = preSolution + /// HideSolutionNode = FALSE + /// EndGlobalSection + ///EndGlobal. + /// + internal static string SlnTemplate { + get { + return ResourceManager.GetString("SlnTemplate", resourceCulture); + } + } + } +} diff --git a/Il2CppDumper/Properties/Resources.resx b/Il2CppDumper/Properties/Resources.resx new file mode 100644 index 0000000..e7de487 --- /dev/null +++ b/Il2CppDumper/Properties/Resources.resx @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + {%PROJECTGUID%}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {%PROJECTGUID%}.Debug|Any CPU.Build.0 = Debug|Any CPU + {%PROJECTGUID%}.Release|Any CPU.ActiveCfg = Release|Any CPU + {%PROJECTGUID%}.Release|Any CPU.Build.0 = Release|Any CPU + + + + Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "%PROJECTNAME%", "%CSPROJRELATIVEPATH%", "{%PROJECTGUID%}" +EndProject + + + + Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +%PROJECTDEFINITIONS% +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution +%PROJECTCONFIGURATIONS% + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal + + + \ No newline at end of file