Initial commit of new UI c# component

This commit is contained in:
LukeFZ
2025-01-25 15:37:43 +01:00
parent ec76447122
commit cc822b418b
21 changed files with 837 additions and 4 deletions

View File

@@ -0,0 +1,8 @@
using System.Text.Json.Serialization;
namespace Il2CppInspector.Redux.GUI;
[JsonSerializable(typeof(string))]
[JsonSerializable(typeof(List<string>))]
[JsonSerializable(typeof(Dictionary<string, string>))]
internal partial class AppJsonSerializerContext : JsonSerializerContext;

View File

@@ -0,0 +1,21 @@
namespace Il2CppInspector.Redux.GUI;
public static class DictionaryExtensions
{
public static bool GetAsBooleanOrDefault(this Dictionary<string, string> dict, string key, bool defaultValue)
{
if (dict.TryGetValue(key, out var value) && bool.TryParse(value, out var boolResult))
return boolResult;
return defaultValue;
}
public static T GetAsEnumOrDefault<T>(this Dictionary<string, string> dict, string key, T defaultValue)
where T : struct, Enum
{
if (dict.TryGetValue(key, out var value) && Enum.TryParse<T>(value, out var enumResult))
return enumResult;
return defaultValue;
}
}

View File

@@ -0,0 +1,47 @@
using Microsoft.AspNetCore.SignalR;
namespace Il2CppInspector.Redux.GUI;
internal class Il2CppHub : Hub
{
public UiContext State
{
get
{
if (!Context.Items.TryGetValue("context", out var context)
|| context is not UiContext ctx)
{
Context.Items["context"] = ctx = new UiContext();
}
return ctx;
}
}
public UiClient Client => new(Clients.Caller);
public async Task OnUiLaunched()
{
await State.Initialize(Client);
}
public async Task SubmitInputFiles(List<string> inputFiles)
{
await State.LoadInputFiles(Client, inputFiles);
}
public async Task QueueExport(string exportTypeId, string outputDirectory, Dictionary<string, string> settings)
{
await State.QueueExport(Client, exportTypeId, outputDirectory, settings);
}
public async Task StartExport()
{
await State.StartExport(Client);
}
public async Task<IEnumerable<string>> GetPotentialUnityVersions()
{
return await State.GetPotentialUnityVersions();
}
}

View File

@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<InvariantGlobalization>true</InvariantGlobalization>
<PublishAot>false</PublishAot>
<!-- todo: enable this once the app is aot compliant! -->
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Bin2Object\Bin2Object\Bin2Object.csproj" />
<ProjectReference Include="..\Il2CppInspector.Common\Il2CppInspector.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,23 @@
namespace Il2CppInspector.Redux.GUI;
public class LoadingSession : IAsyncDisposable
{
private readonly UiClient _client;
private LoadingSession(UiClient client)
{
_client = client;
}
public static async Task<LoadingSession> Start(UiClient client)
{
await client.BeginLoading();
return new LoadingSession(client);
}
public async ValueTask DisposeAsync()
{
await _client.FinishLoading();
GC.SuppressFinalize(this);
}
}

View File

@@ -0,0 +1,79 @@
using Il2CppInspector.Model;
using Il2CppInspector.Outputs;
namespace Il2CppInspector.Redux.GUI.Outputs;
public class CSharpStubOutput : IOutputFormatProvider
{
public static string Id => "cs";
private enum CSharpLayout
{
SingleFile,
Namespace,
Assembly,
Class,
Tree
}
private enum TypeSortingMode
{
Alphabetical,
TypeDefinitionIndex
}
private class Settings(Dictionary<string, string> settings)
{
public readonly CSharpLayout Layout = settings.GetAsEnumOrDefault("layout", CSharpLayout.SingleFile);
public readonly bool FlattenHierarchy = settings.GetAsBooleanOrDefault("flatten", false);
public readonly TypeSortingMode SortingMode = settings.GetAsEnumOrDefault("sorting", TypeSortingMode.Alphabetical);
public readonly bool SuppressMetadata = settings.GetAsBooleanOrDefault("suppressmetadata", false);
public readonly bool MustCompile = settings.GetAsBooleanOrDefault("compilable", false);
public readonly bool SeperateAssemblyAttributes = settings.GetAsBooleanOrDefault("seperateassemblyattributes", true);
}
public async Task Export(AppModel model, UiClient client, string outputPath, Dictionary<string, string> settingsDict)
{
var settings = new Settings(settingsDict);
var writer = new CSharpCodeStubs(model.TypeModel)
{
SuppressMetadata = settings.SuppressMetadata,
MustCompile = settings.MustCompile
};
await client.ShowLogMessage("Writing C# type definitions");
switch (settings.Layout, settings.SortingMode)
{
case (CSharpLayout.SingleFile, TypeSortingMode.TypeDefinitionIndex):
writer.WriteSingleFile(outputPath, info => info.Index);
break;
case (CSharpLayout.SingleFile, TypeSortingMode.Alphabetical):
writer.WriteSingleFile(outputPath, info => info.Name);
break;
case (CSharpLayout.Namespace, TypeSortingMode.TypeDefinitionIndex):
writer.WriteFilesByNamespace(outputPath, info => info.Index, settings.FlattenHierarchy);
break;
case (CSharpLayout.Namespace, TypeSortingMode.Alphabetical):
writer.WriteFilesByNamespace(outputPath, info => info.Name, settings.FlattenHierarchy);
break;
case (CSharpLayout.Assembly, TypeSortingMode.TypeDefinitionIndex):
writer.WriteFilesByAssembly(outputPath, info => info.Index, settings.SeperateAssemblyAttributes);
break;
case (CSharpLayout.Assembly, TypeSortingMode.Alphabetical):
writer.WriteFilesByAssembly(outputPath, info => info.Name, settings.SeperateAssemblyAttributes);
break;
case (CSharpLayout.Class, _):
writer.WriteFilesByClass(outputPath, settings.FlattenHierarchy);
break;
case (CSharpLayout.Tree, _):
writer.WriteFilesByClassTree(outputPath, settings.SeperateAssemblyAttributes);
break;
}
}
}

View File

@@ -0,0 +1,31 @@
using Il2CppInspector.Cpp;
using Il2CppInspector.Cpp.UnityHeaders;
using Il2CppInspector.Model;
using Il2CppInspector.Outputs;
namespace Il2CppInspector.Redux.GUI.Outputs;
public class CppScaffoldingOutput : IOutputFormatProvider
{
public static string Id => "cppscaffolding";
private class Settings(Dictionary<string, string> settings)
{
public readonly string UnityVersion = settings.GetValueOrDefault("unityversion", "");
public readonly CppCompilerType Compiler = settings.GetAsEnumOrDefault("compiler", CppCompilerType.GCC);
}
public async Task Export(AppModel model, UiClient client, string outputPath, Dictionary<string, string> settingsDict)
{
var settings = new Settings(settingsDict);
await client.ShowLogMessage($"Bulding application model for Unity {settings.UnityVersion}/{settings.Compiler}");
model.Build(new UnityVersion(settings.UnityVersion), settings.Compiler);
await client.ShowLogMessage("Generating C++ scaffolding");
var scaffolding = new CppScaffolding(model);
await client.ShowLogMessage("Writing C++ scaffolding");
scaffolding.Write(outputPath);
}
}

View File

@@ -0,0 +1,61 @@
using Il2CppInspector.Cpp;
using Il2CppInspector.Cpp.UnityHeaders;
using Il2CppInspector.Model;
using Il2CppInspector.Outputs;
namespace Il2CppInspector.Redux.GUI.Outputs;
public class DisassemblerMetadataOutput : IOutputFormatProvider
{
public static string Id => "disassemblermetadata";
private enum DisassemblerType
{
IDA,
Ghidra,
BinaryNinja,
None
}
private class Settings(Dictionary<string, string> dict)
{
public readonly DisassemblerType Disassembler = dict.GetAsEnumOrDefault("disassembler", DisassemblerType.IDA);
public readonly string UnityVersion = dict.GetValueOrDefault("unityversion", "");
}
public async Task Export(AppModel model, UiClient client, string outputPath, Dictionary<string, string> settingsDict)
{
var settings = new Settings(settingsDict);
await client.ShowLogMessage($"Bulding application model for Unity {settings.UnityVersion}/{CppCompilerType.GCC}");
model.Build(new UnityVersion(settings.UnityVersion), CppCompilerType.GCC);
var headerPath = Path.Join(outputPath, "il2cpp.h");
{
await client.ShowLogMessage("Generating C++ types");
var cppScaffolding = new CppScaffolding(model, useBetterArraySize: true);
await client.ShowLogMessage("Writing C++ types");
cppScaffolding.WriteTypes(headerPath);
}
var metadataPath = Path.Join(outputPath, "il2cpp.json");
{
await client.ShowLogMessage("Generating disassembler metadata");
var jsonMetadata = new JSONMetadata(model);
await client.ShowLogMessage("Writing disassembler metadata");
jsonMetadata.Write(metadataPath);
}
if (settings.Disassembler != DisassemblerType.None)
{
var scriptPath = Path.Join(outputPath, "il2cpp.py");
await client.ShowLogMessage($"Generating python script for {settings.Disassembler}");
var script = new PythonScript(model);
await client.ShowLogMessage($"Writing python script for {settings.Disassembler}");
script.WriteScriptToFile(scriptPath, settings.Disassembler.ToString(), headerPath, metadataPath);
}
}
}

View File

@@ -0,0 +1,27 @@
using Il2CppInspector.Model;
using Il2CppInspector.Outputs;
namespace Il2CppInspector.Redux.GUI.Outputs;
public class DummyDllOutput : IOutputFormatProvider
{
public static string Id => "dummydlls";
private class Settings(Dictionary<string, string> dict)
{
public readonly bool SuppressMetadata = dict.GetAsBooleanOrDefault("suppressmetadata", false);
}
public async Task Export(AppModel model, UiClient client, string outputPath, Dictionary<string, string> settingsDict)
{
var outputSettings = new Settings(settingsDict);
await client.ShowLogMessage("Generating .NET dummy assemblies");
var shims = new AssemblyShims(model.TypeModel)
{
SuppressMetadata = outputSettings.SuppressMetadata
};
shims.Write(outputPath, client.EventHandler);
}
}

View File

@@ -0,0 +1,14 @@
using Il2CppInspector.Model;
namespace Il2CppInspector.Redux.GUI.Outputs;
public interface IOutputFormat
{
public Task Export(AppModel model, UiClient client, string outputPath,
Dictionary<string, string> settingsDict);
}
public interface IOutputFormatProvider : IOutputFormat
{
public static abstract string Id { get; }
}

View File

@@ -0,0 +1,38 @@
namespace Il2CppInspector.Redux.GUI.Outputs;
public static class OutputFormatRegistry
{
public static IEnumerable<string> AvailableOutputFormats => OutputFormats.Keys;
private static readonly Dictionary<string, IOutputFormat> OutputFormats = [];
public static void RegisterOutputFormat<T>() where T : IOutputFormatProvider, new()
{
if (OutputFormats.ContainsKey(T.Id))
throw new InvalidOperationException("An output format with this id was already registered.");
OutputFormats[T.Id] = new T();
}
public static IOutputFormat GetOutputFormat(string id)
{
if (!OutputFormats.TryGetValue(id, out var format))
throw new ArgumentException($"Failed to find output format for id {id}", nameof(id));
return format;
}
private static void RegisterBuiltinOutputFormats()
{
RegisterOutputFormat<CSharpStubOutput>();
RegisterOutputFormat<VsSolutionOutput>();
RegisterOutputFormat<DummyDllOutput>();
RegisterOutputFormat<DisassemblerMetadataOutput>();
RegisterOutputFormat<CppScaffoldingOutput>();
}
static OutputFormatRegistry()
{
RegisterBuiltinOutputFormats();
}
}

View File

@@ -0,0 +1,29 @@
using Il2CppInspector.Model;
using Il2CppInspector.Outputs;
namespace Il2CppInspector.Redux.GUI.Outputs;
public class VsSolutionOutput : IOutputFormatProvider
{
public static string Id => "vssolution";
private class Settings(Dictionary<string, string> settings)
{
public readonly string UnityPath = settings.GetValueOrDefault("unitypath", "");
public readonly string UnityAssembliesPath = settings.GetValueOrDefault("assembliespath", "");
}
public async Task Export(AppModel model, UiClient client, string outputPath, Dictionary<string, string> settingsDict)
{
var settings = new Settings(settingsDict);
var writer = new CSharpCodeStubs(model.TypeModel)
{
MustCompile = true,
SuppressMetadata = true
};
await client.ShowLogMessage("Writing Visual Studio solution");
writer.WriteSolution(outputPath, settings.UnityPath, settings.UnityAssembliesPath);
}
}

View File

@@ -0,0 +1,54 @@
namespace Il2CppInspector.Redux.GUI;
public static class PathHeuristics
{
private static readonly string[] AllowedMetadataExtensionComponents =
[
"dat", "dec"
];
private static readonly string[] AllowedMetadataNameComponents =
[
"metadata"
];
private static readonly string[] AllowedBinaryPathComponents =
[
"GameAssembly",
"il2cpp",
"UnityFramework"
];
private static readonly string[] AllowedBinaryExtensionComponents =
[
"dll", "so", "exe", "bin", "prx", "sprx", "dylib"
];
public static bool IsMetadataPath(string path)
{
var extension = Path.GetExtension(path);
if (AllowedMetadataExtensionComponents.Any(extension.Contains))
return true;
var filename = Path.GetFileNameWithoutExtension(path);
if (AllowedMetadataNameComponents.Any(filename.Contains))
return true;
return false;
}
public static bool IsBinaryPath(string path)
{
var extension = Path.GetExtension(path);
// empty to allow macho binaries which do not have an extension
if (extension == "" || AllowedBinaryExtensionComponents.Any(extension.Contains))
return true;
var filename = Path.GetFileNameWithoutExtension(path);
if (AllowedBinaryPathComponents.Any(filename.Contains))
return true;
return false;
}
}

View File

@@ -0,0 +1,54 @@
using Il2CppInspector.Redux.GUI;
using Microsoft.AspNetCore.SignalR;
var builder = WebApplication.CreateSlimBuilder(args);
builder.Services.ConfigureHttpJsonOptions(options =>
{
options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
});
builder.Services.AddSignalR(config =>
{
#if DEBUG
config.EnableDetailedErrors = true;
#endif
});
builder.Services.Configure<JsonHubProtocolOptions>(options =>
{
options.PayloadSerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
});
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
{
policy.SetIsOriginAllowed(origin => origin.StartsWith("http://localhost") || origin.StartsWith("http://tauri.localhost"))
.AllowAnyHeader()
.WithMethods("GET", "POST")
.AllowCredentials();
});
});
builder.Services.AddSingleton<UiProcessService>();
builder.Services.AddSingleton<IHostedService>(p => p.GetRequiredService<UiProcessService>());
var app = builder.Build();
app.UseCors();
app.MapHub<Il2CppHub>("/il2cpp");
await app.StartAsync();
var serverUrl = app.Urls.First();
var port = new Uri(serverUrl).Port;
#if DEBUG
Console.WriteLine($"Listening on port {port}");
#else
app.Services.GetRequiredService<UiProcessService>().LaunchUiProcess(port);
#endif
await app.WaitForShutdownAsync();

View File

@@ -0,0 +1,15 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "todos",
"applicationUrl": "http://localhost:5154",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -0,0 +1,44 @@
using Microsoft.AspNetCore.SignalR;
namespace Il2CppInspector.Redux.GUI;
public class UiClient(ISingleClientProxy client)
{
private EventHandler<string>? _handler;
public EventHandler<string> EventHandler
{
get
{
_handler ??= (_, status) =>
{
#pragma warning disable CS4014
ShowLogMessage(status);
#pragma warning restore CS4014
};
return _handler;
}
}
public async Task ShowLogMessage(string message, CancellationToken cancellationToken = default)
=> await client.SendAsync(nameof(ShowLogMessage), message, cancellationToken);
public async Task BeginLoading(CancellationToken cancellationToken = default)
=> await client.SendAsync(nameof(BeginLoading), cancellationToken);
public async Task FinishLoading(CancellationToken cancellationToken = default)
=> await client.SendAsync(nameof(FinishLoading), cancellationToken);
public async Task ShowInfoToast(string message, CancellationToken cancellationToken = default)
=> await client.SendAsync(nameof(ShowInfoToast), message, cancellationToken);
public async Task ShowSuccessToast(string message, CancellationToken cancellationToken = default)
=> await client.SendAsync(nameof(ShowSuccessToast), message, cancellationToken);
public async Task ShowErrorToast(string message, CancellationToken cancellationToken = default)
=> await client.SendAsync(nameof(ShowErrorToast), message, cancellationToken);
public async Task OnImportCompleted(CancellationToken cancellationToken = default)
=> await client.SendAsync(nameof(OnImportCompleted), cancellationToken);
}

View File

@@ -0,0 +1,216 @@
using System.Diagnostics;
using Il2CppInspector.Cpp.UnityHeaders;
using Il2CppInspector.Model;
using Il2CppInspector.Redux.GUI.Outputs;
using Il2CppInspector.Reflection;
using Inspector = Il2CppInspector.Il2CppInspector;
namespace Il2CppInspector.Redux.GUI;
public class UiContext
{
private const string BugReportSuffix =
"""
If you believe this is a bug in Il2CppInspectorRedux, please use the CLI version to generate the complete output and paste it when filing a bug report.
Do not send a screenshot of this error!
""";
private Metadata? _metadata;
private IFileFormatStream? _binary;
private readonly List<AppModel> _appModels = [];
private readonly List<UnityHeaders> _potentialUnityVersions = [];
private readonly LoadOptions _loadOptions = new();
private readonly List<(string FormatId, string OutputDirectory, Dictionary<string, string> Settings)> _queuedExports = [];
private async Task<bool> TryLoadMetadataFromStream(UiClient client, MemoryStream stream)
{
try
{
_metadata = Metadata.FromStream(stream, client.EventHandler);
return true;
}
catch (Exception e)
{
await client.ShowErrorToast($"{e.Message}{BugReportSuffix}");
}
return false;
}
private async Task<bool> TryLoadBinaryFromStream(UiClient client, MemoryStream stream)
{
await client.ShowLogMessage("Processing binary");
try
{
var file = FileFormatStream.Load(stream, _loadOptions, client.EventHandler);
if (file == null)
throw new InvalidOperationException("Failed to determine binary file format.");
if (file.NumImages == 0)
throw new InvalidOperationException("Failed to find any binary images in the file");
_binary = file;
return true;
}
catch (Exception e)
{
await client.ShowErrorToast($"{e.Message}{BugReportSuffix}");
}
return false;
}
private async Task<bool> TryInitializeInspector(UiClient client)
{
Debug.Assert(_binary != null);
Debug.Assert(_metadata != null);
_appModels.Clear();
var inspectors = Inspector.LoadFromStream(_binary, _metadata, client.EventHandler);
if (inspectors.Count == 0)
{
await client.ShowErrorToast(
"""
Failed to auto-detect any IL2CPP binary images in the provided files.
This may mean the binary file is packed, encrypted or obfuscated, that the file
is not an IL2CPP image or that Il2CppInspector was not able to automatically find the required data.
Please check the binary file in a disassembler to ensure that it is an unencrypted IL2CPP binary before submitting a bug report!
""");
return false;
}
foreach (var inspector in inspectors)
{
await client.ShowLogMessage(
$"Building .NET type model for {inspector.BinaryImage.Format}/{inspector.BinaryImage.Arch} image");
try
{
var typeModel = new TypeModel(inspector);
// Just create the app model, do not initialize it - this is done lazily depending on the exports
_appModels.Add(new AppModel(typeModel, makeDefaultBuild: false));
}
catch (Exception e)
{
await client.ShowErrorToast($"Failed to build type model: {e.Message}{BugReportSuffix}");
// Clear out failed metadata and binary so subsequent loads do not use any stale data.
_metadata = null;
_binary = null;
return false;
}
}
_potentialUnityVersions.Clear();
_potentialUnityVersions.AddRange(UnityHeaders.GuessHeadersForBinary(_appModels[0].Package.Binary));
return true;
}
public async Task Initialize(UiClient client, CancellationToken cancellationToken = default)
{
await client.ShowSuccessToast("SignalR initialized!", cancellationToken);
}
public async Task LoadInputFiles(UiClient client, List<string> inputFiles,
CancellationToken cancellationToken = default)
{
await using (await LoadingSession.Start(client))
{
var streams = Inspector.GetStreamsFromPackage(inputFiles);
if (streams != null)
{
// The input files contained a package that provides the metadata and binary.
// Use these instead of parsing all files individually.
if (!await TryLoadMetadataFromStream(client, streams.Value.Metadata))
return;
if (!await TryLoadBinaryFromStream(client, streams.Value.Binary))
return;
}
else
{
foreach (var inputFile in inputFiles)
{
if (_metadata != null && _binary != null)
break;
await client.ShowLogMessage($"Processing {inputFile}", cancellationToken);
var data = await File.ReadAllBytesAsync(inputFile, cancellationToken);
var stream = new MemoryStream(data);
if ( _metadata == null && PathHeuristics.IsMetadataPath(inputFile))
{
if (await TryLoadMetadataFromStream(client, stream))
{
await client.ShowSuccessToast($"Loaded metadata from {inputFile}", cancellationToken);
}
}
else if (_binary == null && PathHeuristics.IsBinaryPath(inputFile))
{
stream.Position = 0;
_loadOptions.BinaryFilePath = inputFile;
if (await TryLoadBinaryFromStream(client, stream))
{
await client.ShowSuccessToast($"Loaded binary from {inputFile}", cancellationToken);
}
}
}
}
if (_metadata != null && _binary != null)
{
if (await TryInitializeInspector(client))
{
await client.ShowSuccessToast("Successfully loaded IL2CPP data!", cancellationToken);
await client.OnImportCompleted(cancellationToken);
}
}
}
}
public Task QueueExport(UiClient client, string exportFormatId, string outputDirectory,
Dictionary<string, string> settings, CancellationToken cancellationToken = default)
{
_queuedExports.Add((exportFormatId, outputDirectory, settings));
return Task.CompletedTask;
}
public async Task StartExport(UiClient client, CancellationToken cancellationToken = default)
{
// todo: support different app model selection (when loading packages)
Debug.Assert(_appModels.Count > 0);
await using (await LoadingSession.Start(client))
{
var model = _appModels[0];
foreach (var queuedExport in _queuedExports)
{
var outputFormat = OutputFormatRegistry.GetOutputFormat(queuedExport.FormatId);
await outputFormat.Export(model, client, queuedExport.OutputDirectory, queuedExport.Settings);
}
_queuedExports.Clear();
}
await client.ShowSuccessToast("Export finished", cancellationToken);
}
public Task<List<string>> GetPotentialUnityVersions()
{
return Task.FromResult(_potentialUnityVersions.Select(x => x.VersionRange.Min.ToString()).ToList());
}
}

View File

@@ -0,0 +1,32 @@
using System.Diagnostics;
namespace Il2CppInspector.Redux.GUI;
public class UiProcessService(IHostApplicationLifetime lifetime) : BackgroundService
{
private const string UiExecutableName = "Il2CppInspector.Redux.GUI.UI.exe";
private Process? _uiProcess;
public void LaunchUiProcess(int port)
{
_uiProcess = Process.Start(new ProcessStartInfo(UiExecutableName, [port.ToString()]));
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (_uiProcess == null)
await Task.Delay(TimeSpan.FromMilliseconds(10), stoppingToken);
await _uiProcess.WaitForExitAsync(stoppingToken);
lifetime.StopApplication();
}
public override Task StopAsync(CancellationToken cancellationToken)
{
if (_uiProcess is { HasExited: false })
_uiProcess.Kill();
return base.StopAsync(cancellationToken);
}
}

View File

@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View File

@@ -44,6 +44,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VersionedSerialization", "V
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VersionedSerialization.Generator", "VersionedSerialization.Generator\VersionedSerialization.Generator.csproj", "{6FF1F0C0-374A-4B7E-B173-697605679AF6}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VersionedSerialization.Generator", "VersionedSerialization.Generator\VersionedSerialization.Generator.csproj", "{6FF1F0C0-374A-4B7E-B173-697605679AF6}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Il2CppInspector.Redux.GUI", "Il2CppInspector.Redux.GUI\Il2CppInspector.Redux.GUI.csproj", "{CB6CE40B-0805-49B1-82DD-4CAAE58F9D6E}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -71,11 +73,15 @@ Global
{A24D77DA-8A64-4AD3-956A-677A96F20373}.Release|Any CPU.ActiveCfg = Release|Any CPU {A24D77DA-8A64-4AD3-956A-677A96F20373}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A24D77DA-8A64-4AD3-956A-677A96F20373}.Release|Any CPU.Build.0 = Release|Any CPU {A24D77DA-8A64-4AD3-956A-677A96F20373}.Release|Any CPU.Build.0 = Release|Any CPU
{803C3421-1907-4114-8B6B-F5E1789FD6A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {803C3421-1907-4114-8B6B-F5E1789FD6A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{803C3421-1907-4114-8B6B-F5E1789FD6A6}.Release|Any CPU.ActiveCfg = Release|AnyCPU {803C3421-1907-4114-8B6B-F5E1789FD6A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{803C3421-1907-4114-8B6B-F5E1789FD6A6}.Release|Any CPU.Build.0 = Release|AnyCPU {803C3421-1907-4114-8B6B-F5E1789FD6A6}.Release|Any CPU.Build.0 = Release|Any CPU
{6FF1F0C0-374A-4B7E-B173-697605679AF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6FF1F0C0-374A-4B7E-B173-697605679AF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6FF1F0C0-374A-4B7E-B173-697605679AF6}.Release|Any CPU.ActiveCfg = Release|AnyCPU {6FF1F0C0-374A-4B7E-B173-697605679AF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6FF1F0C0-374A-4B7E-B173-697605679AF6}.Release|Any CPU.Build.0 = Release|AnyCPU {6FF1F0C0-374A-4B7E-B173-697605679AF6}.Release|Any CPU.Build.0 = Release|Any CPU
{CB6CE40B-0805-49B1-82DD-4CAAE58F9D6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CB6CE40B-0805-49B1-82DD-4CAAE58F9D6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CB6CE40B-0805-49B1-82DD-4CAAE58F9D6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CB6CE40B-0805-49B1-82DD-4CAAE58F9D6E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE