impr: Cleanup .NET script library and API

This commit is contained in:
WerWolv 2024-05-17 20:24:28 +02:00
parent 7a14e3dac4
commit 0453a23b12
6 changed files with 63 additions and 51 deletions

View File

@ -8,20 +8,24 @@ namespace ImHex
public class EntryPoint
{
public static int ExecuteScript(IntPtr arg, int argLength)
private static void Log(string message)
{
Console.WriteLine($"[.NET Script] {message}");
}
public static int ExecuteScript(IntPtr argument, int argumentLength)
{
try
{
return ExecuteScript(Marshal.PtrToStringUTF8(arg, argLength));
return ExecuteScript(Marshal.PtrToStringUTF8(argument, argumentLength));
}
catch (Exception e)
{
Console.WriteLine("[.NET Script] Exception in AssemblyLoader: " + e.ToString());
Log($"Exception in AssemblyLoader: {e}");
return 1;
}
}
private static List<string> loadedPlugins = new();
private static readonly List<string> LoadedPlugins = new();
private static int ExecuteScript(string args)
{
// Parse input in the form of "execType||path"
@ -34,7 +38,7 @@ namespace ImHex
string? basePath = Path.GetDirectoryName(path);
if (basePath == null)
{
Console.WriteLine("[.NET Script] Failed to get base path");
Log("Failed to get base path");
return 1;
}
@ -47,20 +51,19 @@ namespace ImHex
if (type is "LOAD")
{
// If the script has been loaded already, don't do it again
if (loadedPlugins.Contains(path))
if (LoadedPlugins.Contains(path))
{
return 0;
}
// Check if the plugin is already loaded
loadedPlugins.Add(path);
LoadedPlugins.Add(path);
}
// Load all assemblies in the parent folder
foreach (var file in Directory.GetFiles(basePath, "*.dll"))
{
foreach (var file in Directory.GetFiles(basePath, "*.dll")) {
// Skip main Assembly
if (file.EndsWith("Main.dll"))
if (new FileInfo(file).Name == "Main.dll")
{
continue;
}
@ -72,7 +75,7 @@ namespace ImHex
}
catch (Exception e)
{
Console.WriteLine("[.NET Script] Failed to load assembly: " + file + " - " + e);
Log($"Failed to load assembly: {file} - {e}");
}
}
@ -83,7 +86,7 @@ namespace ImHex
var libraryModule = Array.Find(context.Assemblies.ToArray(), module => module.GetName().Name == "ImHexLibrary");
if (libraryModule == null)
{
Console.WriteLine("[.NET Script] Refusing to load non-ImHex script");
Log("Refusing to load non-ImHex script");
return 1;
}
else
@ -92,7 +95,7 @@ namespace ImHex
var libraryType = libraryModule.GetType("Library");
if (libraryType == null)
{
Console.WriteLine("[.NET Script] Failed to find Library type in ImHexLibrary");
Log("Failed to find Library type in ImHexLibrary");
return 1;
}
@ -100,7 +103,7 @@ namespace ImHex
var initMethod = libraryType.GetMethod("Initialize", BindingFlags.Static | BindingFlags.Public);
if (initMethod == null)
{
Console.WriteLine("[.NET Script] Failed to find Initialize method");
Log("Failed to find Initialize method");
return 1;
}
@ -108,13 +111,20 @@ namespace ImHex
initMethod.Invoke(null, null);
}
// Find a class named "Script"
var entryPointType = assembly.GetType("Script");
if (entryPointType == null)
// Find classes derived from IScript
var entryPointTypes = Array.FindAll(assembly.GetTypes(), t => t.GetInterface("IScript") != null);
if (entryPointTypes.Length == 0)
{
Console.WriteLine("[.NET Script] Failed to find Script type");
Log("Failed to find Script entrypoint");
return 1;
} else if (entryPointTypes.Length > 1)
{
Log("Found multiple Script entrypoints");
return 1;
}
var entryPointType = entryPointTypes[0];
if (type is "EXEC" or "LOAD")
{
@ -140,7 +150,7 @@ namespace ImHex
}
catch (Exception e)
{
Console.WriteLine("[.NET Script] Exception in AssemblyLoader: " + e);
Log($"Exception in AssemblyLoader: {e}");
return 3;
}
finally

View File

@ -1,9 +1,16 @@
using ImHex;
public class Library
public static class Library
{
public static void Initialize()
{
Logger.RedirectConsole();
}
}
public interface IScript {
static void Main() { }
static void OnLoad() { }
}

View File

@ -5,7 +5,7 @@ using System.Text;
namespace ImHex
{
public partial class Logger
public static partial class Logger
{
[LibraryImport("ImHex")]
private static partial void logPrintV1(byte[] message);

View File

@ -33,8 +33,8 @@ namespace ImHex
}
public partial class Memory
{
private static List<IProvider> _registeredProviders = new();
private static List<Delegate> _registeredDelegates = new();
private static readonly List<IProvider> RegisteredProviders = new();
private static readonly List<Delegate> RegisteredDelegates = new();
private delegate void DataAccessDelegate(UInt64 address, IntPtr buffer, UInt64 size);
private delegate UInt64 GetSizeDelegate();
@ -95,20 +95,20 @@ namespace ImHex
public static void RegisterProvider<T>() where T : IProvider, new()
{
_registeredProviders.Add(new T());
RegisteredProviders.Add(new T());
ref var provider = ref CollectionsMarshal.AsSpan(_registeredProviders)[^1];
ref var provider = ref CollectionsMarshal.AsSpan(RegisteredProviders)[^1];
_registeredDelegates.Add(new DataAccessDelegate(provider.readRaw));
_registeredDelegates.Add(new DataAccessDelegate(provider.writeRaw));
_registeredDelegates.Add(new GetSizeDelegate(provider.getSize));
RegisteredDelegates.Add(new DataAccessDelegate(provider.readRaw));
RegisteredDelegates.Add(new DataAccessDelegate(provider.writeRaw));
RegisteredDelegates.Add(new GetSizeDelegate(provider.getSize));
registerProviderV1(
Encoding.UTF8.GetBytes(provider.getTypeName()),
Encoding.UTF8.GetBytes(provider.getName()),
Marshal.GetFunctionPointerForDelegate(_registeredDelegates[^3]),
Marshal.GetFunctionPointerForDelegate(_registeredDelegates[^2]),
Marshal.GetFunctionPointerForDelegate(_registeredDelegates[^1])
Marshal.GetFunctionPointerForDelegate(RegisteredDelegates[^3]),
Marshal.GetFunctionPointerForDelegate(RegisteredDelegates[^2]),
Marshal.GetFunctionPointerForDelegate(RegisteredDelegates[^1])
);
}

View File

@ -8,7 +8,7 @@ namespace ImHex
private delegate void DrawContentDelegate();
private delegate void ActionDelegate();
private static List<Delegate> _registeredDelegates = new();
private static readonly List<Delegate> RegisteredDelegates = new();
[LibraryImport("ImHex")]
private static partial void showMessageBoxV1(byte[] message);
@ -48,22 +48,17 @@ namespace ImHex
public static string? ShowInputTextBox(string title, string message, int maxSize)
{
unsafe
{
var buffer = new byte[maxSize];
GCHandle pinnedArray = GCHandle.Alloc(buffer, GCHandleType.Pinned);
showInputTextBoxV1(Encoding.UTF8.GetBytes(title), Encoding.UTF8.GetBytes(message), pinnedArray.AddrOfPinnedObject(), maxSize);
pinnedArray.Free();
var buffer = new byte[maxSize];
GCHandle pinnedArray = GCHandle.Alloc(buffer, GCHandleType.Pinned);
showInputTextBoxV1(Encoding.UTF8.GetBytes(title), Encoding.UTF8.GetBytes(message), pinnedArray.AddrOfPinnedObject(), maxSize);
pinnedArray.Free();
if (buffer.Length == 0 || buffer[0] == '\x00')
{
return null;
}
else
{
return Encoding.UTF8.GetString(buffer);
}
if (buffer.Length == 0 || buffer[0] == '\x00')
{
return null;
}
return Encoding.UTF8.GetString(buffer);
}
public enum ToastType
@ -85,22 +80,22 @@ namespace ImHex
public static void RegisterView(byte[] icon, string name, Action function)
{
_registeredDelegates.Add(new DrawContentDelegate(function));
RegisteredDelegates.Add(new DrawContentDelegate(function));
registerViewV1(
icon,
Encoding.UTF8.GetBytes(name),
Marshal.GetFunctionPointerForDelegate(_registeredDelegates[^1])
Marshal.GetFunctionPointerForDelegate(RegisteredDelegates[^1])
);
}
public static void AddMenuItem(byte[] icon, string menuName, string itemName, Action function)
{
_registeredDelegates.Add(new ActionDelegate(function));
RegisteredDelegates.Add(new ActionDelegate(function));
addMenuItemV1(
icon,
Encoding.UTF8.GetBytes(menuName),
Encoding.UTF8.GetBytes(itemName),
Marshal.GetFunctionPointerForDelegate(_registeredDelegates[^1])
Marshal.GetFunctionPointerForDelegate(RegisteredDelegates[^1])
);
}

View File

@ -1,7 +1,7 @@
using ImHex;
using ImGuiNET;
class Script {
class Script : IScript {
public static void OnLoad()
{