add redux CLI based on redux GUI output formats
This commit is contained in:
136
Il2CppInspector.Redux.CLI/CliClient.cs
Normal file
136
Il2CppInspector.Redux.CLI/CliClient.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using System.Threading.Channels;
|
||||
using Il2CppInspector.Redux.FrontendCore;
|
||||
using Microsoft.AspNetCore.SignalR.Client;
|
||||
using Spectre.Console;
|
||||
|
||||
namespace Il2CppInspector.Redux.CLI;
|
||||
|
||||
public class CliClient : IDisposable
|
||||
{
|
||||
public bool ImportCompleted { get; private set; }
|
||||
|
||||
private volatile int _finishedLoadingCount = 0;
|
||||
|
||||
private readonly HubConnection _connection;
|
||||
private readonly List<IDisposable> _commandListeners = [];
|
||||
|
||||
private Channel<string>? _logMessageChannel;
|
||||
|
||||
public CliClient(HubConnection connection)
|
||||
{
|
||||
_connection = connection;
|
||||
|
||||
_commandListeners.Add(_connection.On<string>(nameof(UiClient.ShowLogMessage), ShowLogMessage));
|
||||
_commandListeners.Add(_connection.On(nameof(UiClient.BeginLoading), BeginLoading));
|
||||
_commandListeners.Add(_connection.On(nameof(UiClient.FinishLoading), FinishLoading));
|
||||
_commandListeners.Add(_connection.On<string>(nameof(UiClient.ShowInfoToast), ShowInfoToast));
|
||||
_commandListeners.Add(_connection.On<string>(nameof(UiClient.ShowSuccessToast), ShowSuccessToast));
|
||||
_commandListeners.Add(_connection.On<string>(nameof(UiClient.ShowErrorToast), ShowErrorToast));
|
||||
_commandListeners.Add(_connection.On(nameof(UiClient.OnImportCompleted), OnImportCompleted));
|
||||
}
|
||||
|
||||
public async ValueTask OnUiLaunched(CancellationToken cancellationToken = default)
|
||||
{
|
||||
await _connection.InvokeAsync(nameof(Il2CppHub.OnUiLaunched), cancellationToken);
|
||||
}
|
||||
|
||||
public async ValueTask SubmitInputFiles(List<string> inputFiles, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await _connection.InvokeAsync(nameof(Il2CppHub.SubmitInputFiles), inputFiles, cancellationToken);
|
||||
}
|
||||
|
||||
public async ValueTask QueueExport(string exportTypeId, string outputDirectory, Dictionary<string, string> settings,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
await _connection.InvokeAsync(nameof(Il2CppHub.QueueExport), exportTypeId, outputDirectory, settings, cancellationToken);
|
||||
}
|
||||
|
||||
public async ValueTask StartExport(CancellationToken cancellationToken = default)
|
||||
{
|
||||
await _connection.InvokeAsync(nameof(Il2CppHub.StartExport), cancellationToken);
|
||||
}
|
||||
|
||||
public async ValueTask<List<string>> GetPotentialUnityVersions(CancellationToken cancellationToken = default)
|
||||
=> await _connection.InvokeAsync<List<string>>(nameof(Il2CppHub.GetPotentialUnityVersions), cancellationToken);
|
||||
|
||||
public async ValueTask ExportIl2CppFiles(string outputDirectory, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await _connection.InvokeAsync(nameof(Il2CppHub.ExportIl2CppFiles), outputDirectory, cancellationToken);
|
||||
}
|
||||
|
||||
public async ValueTask<string> GetInspectorVersion(CancellationToken cancellationToken = default)
|
||||
=> await _connection.InvokeAsync<string>(nameof(Il2CppHub.GetInspectorVersion), cancellationToken);
|
||||
|
||||
public async ValueTask WaitForLoadingToFinishAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
var currentLoadingCount = _finishedLoadingCount;
|
||||
while (_finishedLoadingCount == currentLoadingCount)
|
||||
await Task.Delay(10, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task ShowLogMessage(string message)
|
||||
{
|
||||
if (_logMessageChannel == null)
|
||||
{
|
||||
AnsiConsole.MarkupLine($"[white bold]{message}[/]");
|
||||
return;
|
||||
}
|
||||
|
||||
await _logMessageChannel.Writer.WriteAsync(message);
|
||||
}
|
||||
|
||||
private void BeginLoading()
|
||||
{
|
||||
_logMessageChannel = Channel.CreateUnbounded<string>(new UnboundedChannelOptions
|
||||
{
|
||||
SingleReader = true,
|
||||
SingleWriter = true,
|
||||
AllowSynchronousContinuations = true
|
||||
});
|
||||
|
||||
AnsiConsole.Status()
|
||||
.Spinner(Spinner.Known.Triangle)
|
||||
.StartAsync("Loading", async ctx =>
|
||||
{
|
||||
await foreach (var newLogMessage in _logMessageChannel.Reader.ReadAllAsync())
|
||||
{
|
||||
ctx.Status(newLogMessage);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void FinishLoading()
|
||||
{
|
||||
_logMessageChannel?.Writer.Complete();
|
||||
Interlocked.Increment(ref _finishedLoadingCount);
|
||||
}
|
||||
|
||||
private static void ShowInfoToast(string message)
|
||||
{
|
||||
AnsiConsole.MarkupLineInterpolated($"[bold white]INFO: {message}[/]");
|
||||
}
|
||||
|
||||
private static void ShowSuccessToast(string message)
|
||||
{
|
||||
AnsiConsole.MarkupLineInterpolated($"[bold][green]SUCCESS: [/] [white]{message}[/][/]");
|
||||
}
|
||||
|
||||
private static void ShowErrorToast(string message)
|
||||
{
|
||||
AnsiConsole.MarkupLineInterpolated($"[bold][red]ERROR: [/] [white]{message}[/][/]");
|
||||
}
|
||||
|
||||
private void OnImportCompleted()
|
||||
{
|
||||
ImportCompleted = true;
|
||||
}
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
|
||||
foreach (var listener in _commandListeners)
|
||||
listener.Dispose();
|
||||
}
|
||||
}
|
||||
38
Il2CppInspector.Redux.CLI/Commands/BaseCommand.cs
Normal file
38
Il2CppInspector.Redux.CLI/Commands/BaseCommand.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using Il2CppInspector.Redux.FrontendCore;
|
||||
using Microsoft.AspNetCore.SignalR.Client;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Il2CppInspector.Redux.CLI.Commands;
|
||||
|
||||
internal abstract class BaseCommand<T>(PortProvider portProvider) : AsyncCommand<T> where T : CommandSettings
|
||||
{
|
||||
private const string HubPath = "/il2cpp"; // TODO: Make this into a shared constant
|
||||
|
||||
private readonly int _serverPort = portProvider.Port;
|
||||
|
||||
protected abstract Task<int> ExecuteAsync(CliClient client, T settings);
|
||||
|
||||
public override async Task<int> ExecuteAsync(CommandContext context, T settings)
|
||||
{
|
||||
var connection = new HubConnectionBuilder().WithUrl($"http://localhost:{_serverPort}{HubPath}")
|
||||
.AddJsonProtocol(options =>
|
||||
{
|
||||
options.PayloadSerializerOptions.TypeInfoResolverChain.Insert(0,
|
||||
FrontendCoreJsonSerializerContext.Default);
|
||||
})
|
||||
.Build();
|
||||
|
||||
await connection.StartAsync();
|
||||
|
||||
int result;
|
||||
using (var client = new CliClient(connection))
|
||||
{
|
||||
await client.OnUiLaunched();
|
||||
result = await ExecuteAsync(client, settings);
|
||||
}
|
||||
|
||||
await connection.StopAsync();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
17
Il2CppInspector.Redux.CLI/Commands/InteractiveCommand.cs
Normal file
17
Il2CppInspector.Redux.CLI/Commands/InteractiveCommand.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using Microsoft.AspNetCore.SignalR.Client;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Il2CppInspector.Redux.CLI.Commands;
|
||||
|
||||
internal class InteractiveCommand(PortProvider portProvider) : BaseCommand<InteractiveCommand.Options>(portProvider)
|
||||
{
|
||||
public class Options : CommandSettings;
|
||||
|
||||
protected override async Task<int> ExecuteAsync(CliClient client, Options settings)
|
||||
{
|
||||
await Task.Delay(1000);
|
||||
await AnsiConsole.AskAsync<string>("meow?");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
21
Il2CppInspector.Redux.CLI/Commands/ManualCommand.cs
Normal file
21
Il2CppInspector.Redux.CLI/Commands/ManualCommand.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Il2CppInspector.Redux.CLI.Commands;
|
||||
|
||||
internal abstract class ManualCommand<T>(PortProvider portProvider) : BaseCommand<T>(portProvider) where T : ManualCommandOptions
|
||||
{
|
||||
public override ValidationResult Validate(CommandContext context, T settings)
|
||||
{
|
||||
foreach (var inputPath in settings.InputPaths)
|
||||
{
|
||||
if (!Path.Exists(inputPath))
|
||||
return ValidationResult.Error($"Provided input path {inputPath} does not exit.");
|
||||
}
|
||||
|
||||
if (File.Exists(settings.OutputPath))
|
||||
return ValidationResult.Error("Provided output path already exists as a file.");
|
||||
|
||||
return ValidationResult.Success();
|
||||
}
|
||||
}
|
||||
15
Il2CppInspector.Redux.CLI/Commands/ManualCommandOptions.cs
Normal file
15
Il2CppInspector.Redux.CLI/Commands/ManualCommandOptions.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.ComponentModel;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Il2CppInspector.Redux.CLI.Commands;
|
||||
|
||||
internal class ManualCommandOptions : CommandSettings
|
||||
{
|
||||
[CommandArgument(0, "<InputPath>")]
|
||||
[Description("Paths to the input files. Will be subsequently loaded until binary and metadata were found.")]
|
||||
public string[] InputPaths { get; init; } = [];
|
||||
|
||||
[CommandOption("-o|--output")]
|
||||
[Description("Path to the output folder")]
|
||||
public string OutputPath { get; init; } = "";
|
||||
}
|
||||
172
Il2CppInspector.Redux.CLI/Commands/ProcessCommand.cs
Normal file
172
Il2CppInspector.Redux.CLI/Commands/ProcessCommand.cs
Normal file
@@ -0,0 +1,172 @@
|
||||
using Il2CppInspector.Cpp;
|
||||
using Il2CppInspector.Redux.FrontendCore.Outputs;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Il2CppInspector.Redux.CLI.Commands;
|
||||
|
||||
internal class ProcessCommand(PortProvider portProvider) : ManualCommand<ProcessCommand.Option>(portProvider)
|
||||
{
|
||||
// NOTE: There might be a better option than replicating all available flags here (and in the TS UI).
|
||||
// Investigate this in the future.
|
||||
|
||||
public class Option : ManualCommandOptions
|
||||
{
|
||||
// C++ Scaffolding
|
||||
[CommandOption("--output-cpp-scaffolding")]
|
||||
public bool CppScaffolding { get; init; } = false;
|
||||
|
||||
[CommandOption("--unity-version")]
|
||||
public string? UnityVersion { get; init; }
|
||||
|
||||
[CommandOption("--compiler-type")]
|
||||
public CppCompilerType CompilerType { get; init; } = CppCompilerType.GCC;
|
||||
|
||||
// C# stub
|
||||
[CommandOption("-s|--output-csharp-stub")]
|
||||
public bool CSharpStubs { get; init; } = false;
|
||||
|
||||
[CommandOption("--layout")]
|
||||
public CSharpLayout Layout { get; init; } = CSharpLayout.SingleFile;
|
||||
|
||||
[CommandOption("--flatten-hierarchy")]
|
||||
public bool FlattenHierarchy { get; init; } = false;
|
||||
|
||||
[CommandOption("--sorting-mode")]
|
||||
public TypeSortingMode SortingMode { get; init; } = TypeSortingMode.Alphabetical;
|
||||
|
||||
[CommandOption("--suppress-metadata")]
|
||||
public bool SuppressMetadata { get; init; } = false;
|
||||
|
||||
[CommandOption("--compilable")]
|
||||
public bool MustCompile { get; init; } = false;
|
||||
|
||||
[CommandOption("--separate-assembly-attributes")]
|
||||
public bool SeparateAssemblyAttributes { get; init; } = true;
|
||||
|
||||
// Disassembler metadata
|
||||
[CommandOption("-m|--output-disassembler-metadata")]
|
||||
public bool DisassemblerMetadata { get; init; } = false;
|
||||
|
||||
[CommandOption("--disassembler")]
|
||||
public DisassemblerType Disassembler { get; init; } = DisassemblerType.IDA;
|
||||
|
||||
// Dummy DLL output
|
||||
[CommandOption("-d|--output-dummy-dlls")]
|
||||
public bool DummyDlls { get; init; } = false;
|
||||
|
||||
// Visual Studio solution
|
||||
[CommandOption("--output-vs-solution")]
|
||||
public bool VsSolution { get; init; } = false;
|
||||
|
||||
[CommandOption("--unity-path")]
|
||||
public string? UnityPath { get; init; }
|
||||
|
||||
[CommandOption("--unity-assemblies-path")]
|
||||
public string? UnityAssembliesPath { get; init; }
|
||||
|
||||
[CommandOption("--extract-il2cpp-files")]
|
||||
public string? ExtractIl2CppFilesPath { get; init; }
|
||||
}
|
||||
|
||||
protected override async Task<int> ExecuteAsync(CliClient client, Option settings)
|
||||
{
|
||||
var inspectorVersion = await client.GetInspectorVersion();
|
||||
AnsiConsole.MarkupLineInterpolated($"Using inspector [gray]{inspectorVersion}[/]");
|
||||
|
||||
await client.SubmitInputFiles(settings.InputPaths.ToList());
|
||||
await client.WaitForLoadingToFinishAsync();
|
||||
if (!client.ImportCompleted)
|
||||
{
|
||||
AnsiConsole.MarkupLine("[bold][red]FAILED[/] to load IL2CPP data from the given inputs.[/]");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (settings.ExtractIl2CppFilesPath != null)
|
||||
{
|
||||
await client.ExportIl2CppFiles(settings.ExtractIl2CppFilesPath);
|
||||
await client.WaitForLoadingToFinishAsync();
|
||||
}
|
||||
|
||||
var unityVersions = await client.GetPotentialUnityVersions();
|
||||
|
||||
if (settings.CppScaffolding)
|
||||
{
|
||||
var directory = Path.Join(settings.OutputPath, "cpp");
|
||||
await client.QueueExport(CppScaffoldingOutput.Id, directory, new Dictionary<string, string>
|
||||
{
|
||||
["unityversion"] = settings.UnityVersion ?? unityVersions.First(),
|
||||
["compilertype"] = settings.CompilerType.ToString()
|
||||
});
|
||||
}
|
||||
|
||||
if (settings.CSharpStubs)
|
||||
{
|
||||
var directory = Path.Join(settings.OutputPath, "cs");
|
||||
await client.QueueExport(CSharpStubOutput.Id, directory, new Dictionary<string, string>
|
||||
{
|
||||
["layout"] = settings.Layout.ToString(),
|
||||
["flattenhierarchy"] = settings.FlattenHierarchy.ToString(),
|
||||
["sortingmode"] = settings.SortingMode.ToString(),
|
||||
["suppressmetadata"] = settings.SuppressMetadata.ToString(),
|
||||
["mustcompile"] = settings.MustCompile.ToString(),
|
||||
["separateassemblyattributes"] = settings.SeparateAssemblyAttributes.ToString()
|
||||
});
|
||||
}
|
||||
|
||||
if (settings.DisassemblerMetadata)
|
||||
{
|
||||
await client.QueueExport(DisassemblerMetadataOutput.Id, settings.OutputPath,
|
||||
new Dictionary<string, string>
|
||||
{
|
||||
["disassembler"] = settings.Disassembler.ToString(),
|
||||
["unityversion"] = settings.UnityVersion ?? unityVersions.First()
|
||||
});
|
||||
}
|
||||
|
||||
if (settings.DummyDlls)
|
||||
{
|
||||
var directory = Path.Join(settings.OutputPath, "dll");
|
||||
await client.QueueExport(DummyDllOutput.Id, directory, new Dictionary<string, string>
|
||||
{
|
||||
["suppressmetadata"] = settings.SuppressMetadata.ToString()
|
||||
});
|
||||
}
|
||||
|
||||
if (settings.VsSolution)
|
||||
{
|
||||
var directory = Path.Join(settings.OutputPath, "vs");
|
||||
await client.QueueExport(VsSolutionOutput.Id, directory, new Dictionary<string, string>
|
||||
{
|
||||
["unitypath"] = settings.UnityPath ?? "",
|
||||
["unityassembliespath"] = settings.UnityAssembliesPath ?? ""
|
||||
});
|
||||
}
|
||||
|
||||
await client.StartExport();
|
||||
await client.WaitForLoadingToFinishAsync();
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override ValidationResult Validate(CommandContext context, Option settings)
|
||||
{
|
||||
if (settings.UnityPath != null && !Path.Exists(settings.UnityPath))
|
||||
return ValidationResult.Error($"Provided Unity path {settings.UnityPath} does not exist.");
|
||||
|
||||
if (settings.UnityAssembliesPath != null && !Path.Exists(settings.UnityAssembliesPath))
|
||||
return ValidationResult.Error($"Provided Unity assemblies path {settings.UnityAssembliesPath} does not exist.");
|
||||
|
||||
if (settings.ExtractIl2CppFilesPath != null && File.Exists(settings.ExtractIl2CppFilesPath))
|
||||
return ValidationResult.Error(
|
||||
$"Provided extracted IL2CPP files path {settings.ExtractIl2CppFilesPath} already exists as a file.");
|
||||
|
||||
if (settings is
|
||||
{
|
||||
CppScaffolding: false, CSharpStubs: false, DisassemblerMetadata: false, DummyDlls: false,
|
||||
VsSolution: false
|
||||
})
|
||||
return ValidationResult.Error("At least one output format must be specified.");
|
||||
|
||||
return base.Validate(context, settings);
|
||||
}
|
||||
}
|
||||
20
Il2CppInspector.Redux.CLI/Il2CppInspector.Redux.CLI.csproj
Normal file
20
Il2CppInspector.Redux.CLI/Il2CppInspector.Redux.CLI.csproj
Normal file
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<InvariantGlobalization>true</InvariantGlobalization>
|
||||
<PublishAot>true</PublishAot>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.7" />
|
||||
<PackageReference Include="Spectre.Console.Cli" Version="0.50.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Il2CppInspector.Redux.FrontendCore\Il2CppInspector.Redux.FrontendCore.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
6
Il2CppInspector.Redux.CLI/PortProvider.cs
Normal file
6
Il2CppInspector.Redux.CLI/PortProvider.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace Il2CppInspector.Redux.CLI;
|
||||
|
||||
internal sealed class PortProvider(int port)
|
||||
{
|
||||
public int Port => port;
|
||||
}
|
||||
46
Il2CppInspector.Redux.CLI/Program.cs
Normal file
46
Il2CppInspector.Redux.CLI/Program.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using Il2CppInspector.Redux.CLI;
|
||||
using Il2CppInspector.Redux.CLI.Commands;
|
||||
using Il2CppInspector.Redux.FrontendCore;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
var builder = WebApplication.CreateSlimBuilder();
|
||||
|
||||
builder.Services.ConfigureHttpJsonOptions(options =>
|
||||
{
|
||||
options.SerializerOptions.TypeInfoResolverChain.Insert(0, FrontendCoreJsonSerializerContext.Default);
|
||||
});
|
||||
|
||||
builder.Services.Configure<JsonHubProtocolOptions>(options =>
|
||||
{
|
||||
options.PayloadSerializerOptions.TypeInfoResolverChain.Insert(0, FrontendCoreJsonSerializerContext.Default);
|
||||
});
|
||||
|
||||
builder.Services.AddFrontendCore();
|
||||
builder.Logging.ClearProviders();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
app.UseCors();
|
||||
|
||||
app.MapFrontendCore();
|
||||
|
||||
await app.StartAsync();
|
||||
|
||||
var serverUrl = app.Urls.First();
|
||||
var port = new Uri(serverUrl).Port;
|
||||
|
||||
var commandServiceProvider = new ServiceCollection();
|
||||
commandServiceProvider.AddSingleton(new PortProvider(port));
|
||||
|
||||
var commandTypeRegistrar = new ServiceTypeRegistrar(commandServiceProvider);
|
||||
var consoleApp = new CommandApp<InteractiveCommand>(commandTypeRegistrar);
|
||||
|
||||
consoleApp.Configure(config =>
|
||||
{
|
||||
config.AddCommand<ProcessCommand>("process")
|
||||
.WithDescription("Processes the provided input data into one or more output formats.");
|
||||
});
|
||||
|
||||
await consoleApp.RunAsync(args);
|
||||
await app.StopAsync();
|
||||
23
Il2CppInspector.Redux.CLI/Properties/launchSettings.json
Normal file
23
Il2CppInspector.Redux.CLI/Properties/launchSettings.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"profiles": {
|
||||
"WSL": {
|
||||
"commandName": "WSL2",
|
||||
"launchUrl": "http://localhost:5118/",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||
"ASPNETCORE_URLS": "http://localhost:5118"
|
||||
},
|
||||
"distributionName": ""
|
||||
},
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "process -d --disassembler ghidra M:\\Downloads\\Reversing\\NotYetAnalyzedAPKs\\pokemon_friends\\libil2cpp.so M:\\Downloads\\Reversing\\NotYetAnalyzedAPKs\\pokemon_friends\\global-metadata.dat",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"dotnetRunMessages": true,
|
||||
"applicationUrl": "http://localhost:5118"
|
||||
}
|
||||
},
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json"
|
||||
}
|
||||
30
Il2CppInspector.Redux.CLI/ServiceTypeRegistrar.cs
Normal file
30
Il2CppInspector.Redux.CLI/ServiceTypeRegistrar.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Il2CppInspector.Redux.CLI;
|
||||
|
||||
public class ServiceTypeRegistrar(IServiceCollection serviceCollection) : ITypeRegistrar
|
||||
{
|
||||
private readonly IServiceCollection _serviceCollection = serviceCollection;
|
||||
private ServiceTypeResolver? _resolver;
|
||||
|
||||
public void Register(Type service, Type implementation)
|
||||
{
|
||||
_serviceCollection.AddSingleton(service, implementation);
|
||||
}
|
||||
|
||||
public void RegisterInstance(Type service, object implementation)
|
||||
{
|
||||
_serviceCollection.AddSingleton(service, implementation);
|
||||
}
|
||||
|
||||
public void RegisterLazy(Type service, Func<object> factory)
|
||||
{
|
||||
_serviceCollection.AddSingleton(service, _ => factory());
|
||||
}
|
||||
|
||||
public ITypeResolver Build()
|
||||
{
|
||||
_resolver ??= new ServiceTypeResolver(_serviceCollection.BuildServiceProvider());
|
||||
return _resolver;
|
||||
}
|
||||
}
|
||||
13
Il2CppInspector.Redux.CLI/ServiceTypeResolver.cs
Normal file
13
Il2CppInspector.Redux.CLI/ServiceTypeResolver.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Il2CppInspector.Redux.CLI;
|
||||
|
||||
public class ServiceTypeResolver(IServiceProvider serviceProvider) : ITypeResolver
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider = serviceProvider;
|
||||
|
||||
public object? Resolve(Type? type)
|
||||
=> type == null
|
||||
? null
|
||||
: _serviceProvider.GetService(type);
|
||||
}
|
||||
8
Il2CppInspector.Redux.CLI/appsettings.Development.json
Normal file
8
Il2CppInspector.Redux.CLI/appsettings.Development.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
9
Il2CppInspector.Redux.CLI/appsettings.json
Normal file
9
Il2CppInspector.Redux.CLI/appsettings.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
@@ -48,6 +48,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Il2CppInspector.Redux.GUI",
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Il2CppInspector.Redux.FrontendCore", "Il2CppInspector.Redux.FrontendCore\Il2CppInspector.Redux.FrontendCore.csproj", "{D80D0FCE-4C9C-4BF1-8936-71DFB0B2D86A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Il2CppInspector.Redux.CLI", "Il2CppInspector.Redux.CLI\Il2CppInspector.Redux.CLI.csproj", "{8FA27979-23F4-4A4E-8B69-503A20BF1344}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -88,6 +90,10 @@ Global
|
||||
{D80D0FCE-4C9C-4BF1-8936-71DFB0B2D86A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D80D0FCE-4C9C-4BF1-8936-71DFB0B2D86A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D80D0FCE-4C9C-4BF1-8936-71DFB0B2D86A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8FA27979-23F4-4A4E-8B69-503A20BF1344}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8FA27979-23F4-4A4E-8B69-503A20BF1344}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8FA27979-23F4-4A4E-8B69-503A20BF1344}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8FA27979-23F4-4A4E-8B69-503A20BF1344}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
Reference in New Issue
Block a user