GUI: Don't lose status handler on multi-image binaries / improve status output

This commit is contained in:
Katy Coe
2020-08-07 19:08:07 +02:00
parent 58cd9abe02
commit 7086a8f7ba
5 changed files with 20 additions and 15 deletions

View File

@@ -52,7 +52,7 @@ namespace Il2CppInspector
U ReadObject<U>() where U : new(); U ReadObject<U>() where U : new();
string ReadMappedNullTerminatedString(ulong uiAddr); string ReadMappedNullTerminatedString(ulong uiAddr);
List<U> ReadMappedObjectPointerArray<U>(ulong uiAddr, int count) where U : new(); List<U> ReadMappedObjectPointerArray<U>(ulong uiAddr, int count) where U : new();
event EventHandler<string> OnStatusUpdate; EventHandler<string> OnStatusUpdate { get; set; }
} }
public class FileFormatReader public class FileFormatReader
@@ -99,7 +99,7 @@ namespace Il2CppInspector
public virtual int Bits => throw new NotImplementedException(); public virtual int Bits => throw new NotImplementedException();
public event EventHandler<string> OnStatusUpdate; public EventHandler<string> OnStatusUpdate { get; set; }
protected void StatusUpdate(string status) => OnStatusUpdate?.Invoke(this, status); protected void StatusUpdate(string status) => OnStatusUpdate?.Invoke(this, status);
@@ -118,7 +118,9 @@ namespace Il2CppInspector
public static T Load(Stream stream, EventHandler<string> statusCallback = null) { public static T Load(Stream stream, EventHandler<string> statusCallback = null) {
// Copy the original stream in case we modify it // Copy the original stream in case we modify it
var ms = new MemoryStream(); var ms = new MemoryStream();
stream.Position = 0;
if (stream.CanSeek)
stream.Position = 0;
stream.CopyTo(ms); stream.CopyTo(ms);
ms.Position = 0; ms.Position = 0;
@@ -127,7 +129,7 @@ namespace Il2CppInspector
} }
private bool InitImpl(EventHandler<string> statusCallback = null) { private bool InitImpl(EventHandler<string> statusCallback = null) {
OnStatusUpdate += statusCallback; OnStatusUpdate = statusCallback;
return Init(); return Init();
} }

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2017-2019 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com Copyright 2017-2020 Katy Coe - http://www.djkaty.com - https://github.com/djkaty
All rights reserved. All rights reserved.
*/ */
@@ -39,7 +39,7 @@ namespace Il2CppInspector
Endianness = Endianness.Little; Endianness = Endianness.Little;
using var s = new MemoryStream(ReadBytes((int) arch.Size)); using var s = new MemoryStream(ReadBytes((int) arch.Size));
return (IFileFormatReader) MachOReader32.Load(s) ?? MachOReader64.Load(s); return (IFileFormatReader) MachOReader32.Load(s, OnStatusUpdate) ?? MachOReader64.Load(s, OnStatusUpdate);
} }
} }
} }

View File

@@ -33,6 +33,8 @@ namespace Il2CppInspectorGUI
// Attempt to load an IL2CPP application package (APK or IPA) // Attempt to load an IL2CPP application package (APK or IPA)
public async Task<bool> LoadPackageAsync(string packageFile) { public async Task<bool> LoadPackageAsync(string packageFile) {
try { try {
OnStatusUpdate?.Invoke(this, "Extracting package");
var streams = Inspector.GetStreamsFromPackage(packageFile); var streams = Inspector.GetStreamsFromPackage(packageFile);
if (streams == null) if (streams == null)
throw new InvalidOperationException("The supplied package is not an APK or IPA file, or does not contain an IL2CPP application"); throw new InvalidOperationException("The supplied package is not an APK or IPA file, or does not contain an IL2CPP application");
@@ -55,6 +57,7 @@ namespace Il2CppInspectorGUI
Task.Run(() => { Task.Run(() => {
try { try {
OnStatusUpdate?.Invoke(this, "Processing metadata"); OnStatusUpdate?.Invoke(this, "Processing metadata");
metadata = new Metadata(metadataStream); metadata = new Metadata(metadataStream);
return true; return true;
} }
@@ -73,19 +76,21 @@ namespace Il2CppInspectorGUI
public Task<bool> LoadBinaryAsync(Stream binaryStream) => public Task<bool> LoadBinaryAsync(Stream binaryStream) =>
Task.Run(() => { Task.Run(() => {
try { try {
OnStatusUpdate?.Invoke(this, "Processing binary");
// This may throw other exceptions from the individual loaders as well // This may throw other exceptions from the individual loaders as well
IFileFormatReader stream = FileFormatReader.Load(binaryStream, StatusUpdate); IFileFormatReader stream = FileFormatReader.Load(binaryStream, StatusUpdate);
if (stream == null) { if (stream == null) {
throw new InvalidOperationException("Could not determine the binary file format"); throw new InvalidOperationException("Could not determine the binary file format");
} }
if (!stream.Images.Any()) { if (stream.NumImages == 0) {
throw new InvalidOperationException("Could not find any binary images in the file"); throw new InvalidOperationException("Could not find any binary images in the file");
} }
// Multi-image binaries may contain more than one Il2Cpp image // Multi-image binaries may contain more than one Il2Cpp image
AppModels.Clear(); AppModels.Clear();
foreach (var image in stream.Images) { foreach (var image in stream.Images) {
OnStatusUpdate?.Invoke(this, "Analyzing IL2CPP data"); OnStatusUpdate?.Invoke(this, $"Analyzing IL2CPP data for {image.Format}/{image.Arch} image");
// Architecture-agnostic load attempt // Architecture-agnostic load attempt
try { try {
@@ -94,7 +99,7 @@ namespace Il2CppInspectorGUI
var inspector = new Inspector(binary, metadata); var inspector = new Inspector(binary, metadata);
// Build type model // Build type model
OnStatusUpdate?.Invoke(this, "Building .NET type model"); OnStatusUpdate?.Invoke(this, $"Building .NET type model for {image.Format}/{image.Arch} image");
var typeModel = new TypeModel(inspector); var typeModel = new TypeModel(inspector);
// Initialize (but don't build) application model // Initialize (but don't build) application model

View File

@@ -471,7 +471,7 @@
</Button> </Button>
<!-- Busy indicator --> <!-- Busy indicator -->
<Border Name="areaBusyIndicator" Width="500" BorderThickness="1" CornerRadius="2" BorderBrush="Gray" HorizontalAlignment="Center" VerticalAlignment="Center" Background="White" SnapsToDevicePixels="True" Visibility="Hidden"> <Border Name="areaBusyIndicator" Width="800" BorderThickness="1" CornerRadius="2" BorderBrush="Gray" HorizontalAlignment="Center" VerticalAlignment="Center" Background="White" SnapsToDevicePixels="True" Visibility="Hidden">
<StackPanel Margin="60,40,60,40"> <StackPanel Margin="60,40,60,40">
<TextBlock Name="txtBusyStatus" Foreground="{StaticResource WindowsBlue}" FontSize="24" HorizontalAlignment="Center">Getting things ready...</TextBlock> <TextBlock Name="txtBusyStatus" Foreground="{StaticResource WindowsBlue}" FontSize="24" HorizontalAlignment="Center">Getting things ready...</TextBlock>
<Image gif:AnimationBehavior.SourceUri="Resources/pizza.gif" Width="100" Margin="0,20,0,0" RenderOptions.BitmapScalingMode="Fant" /> <Image gif:AnimationBehavior.SourceUri="Resources/pizza.gif" Width="100" Margin="0,20,0,0" RenderOptions.BitmapScalingMode="Fant" />

View File

@@ -118,7 +118,6 @@ namespace Il2CppInspectorGUI
private async Task LoadBinaryAsync(string filename) { private async Task LoadBinaryAsync(string filename) {
var app = (App) Application.Current; var app = (App) Application.Current;
txtBusyStatus.Text = "Processing binary...";
areaBusyIndicator.Visibility = Visibility.Visible; areaBusyIndicator.Visibility = Visibility.Visible;
btnSelectBinaryFile.Visibility = Visibility.Hidden; btnSelectBinaryFile.Visibility = Visibility.Hidden;
@@ -155,7 +154,6 @@ namespace Il2CppInspectorGUI
private async Task LoadPackageAsync(string filename) { private async Task LoadPackageAsync(string filename) {
var app = (App) Application.Current; var app = (App) Application.Current;
txtBusyStatus.Text = "Extracting package...";
areaBusyIndicator.Visibility = Visibility.Visible; areaBusyIndicator.Visibility = Visibility.Visible;
grdFirstPage.Visibility = Visibility.Hidden; grdFirstPage.Visibility = Visibility.Hidden;
@@ -439,7 +437,7 @@ namespace Il2CppInspectorGUI
var selectedPyUnityVersion = ((UnityHeaders) cboPyUnityVersion.SelectedItem)?.VersionRange.Min; var selectedPyUnityVersion = ((UnityHeaders) cboPyUnityVersion.SelectedItem)?.VersionRange.Min;
var selectedPyTarget = (string) cboPyTarget.SelectedItem; var selectedPyTarget = (string) cboPyTarget.SelectedItem;
await Task.Run(() => { await Task.Run(() => {
OnStatusUpdate(this, "Building C++ application model"); OnStatusUpdate(this, "Building application model");
model.Build(selectedPyUnityVersion, CppCompilerType.GCC); model.Build(selectedPyUnityVersion, CppCompilerType.GCC);
OnStatusUpdate(this, $"Generating {selectedPyTarget} Python script"); OnStatusUpdate(this, $"Generating {selectedPyTarget} Python script");
@@ -464,7 +462,7 @@ namespace Il2CppInspectorGUI
var selectedCppUnityVersion = ((UnityHeaders) cboCppUnityVersion.SelectedItem)?.VersionRange.Min; var selectedCppUnityVersion = ((UnityHeaders) cboCppUnityVersion.SelectedItem)?.VersionRange.Min;
var cppCompiler = (CppCompilerType) Enum.Parse(typeof(CppCompilerType), cboCppCompiler.SelectionBoxItem.ToString()); var cppCompiler = (CppCompilerType) Enum.Parse(typeof(CppCompilerType), cboCppCompiler.SelectionBoxItem.ToString());
await Task.Run(() => { await Task.Run(() => {
OnStatusUpdate(this, "Building C++ application model"); OnStatusUpdate(this, "Building application model");
model.Build(selectedCppUnityVersion, cppCompiler); model.Build(selectedCppUnityVersion, cppCompiler);
OnStatusUpdate(this, "Generating C++ scaffolding"); OnStatusUpdate(this, "Generating C++ scaffolding");
@@ -490,7 +488,7 @@ namespace Il2CppInspectorGUI
areaBusyIndicator.Visibility = Visibility.Visible; areaBusyIndicator.Visibility = Visibility.Visible;
var selectedJsonUnityVersion = ((UnityHeaders) cboJsonUnityVersion.SelectedItem)?.VersionRange.Min; var selectedJsonUnityVersion = ((UnityHeaders) cboJsonUnityVersion.SelectedItem)?.VersionRange.Min;
await Task.Run(() => { await Task.Run(() => {
OnStatusUpdate(this, "Building C++ application model"); OnStatusUpdate(this, "Building application model");
model.Build(selectedJsonUnityVersion, CppCompilerType.GCC); model.Build(selectedJsonUnityVersion, CppCompilerType.GCC);
OnStatusUpdate(this, "Generating JSON metadata file"); OnStatusUpdate(this, "Generating JSON metadata file");