Added demo for cpp module and updated the CppModule
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -459,4 +459,5 @@ $RECYCLE.BIN/
|
|||||||
/WebUI_Old/Data
|
/WebUI_Old/Data
|
||||||
/WebUI/bin
|
/WebUI/bin
|
||||||
/WebUI_Old/bin
|
/WebUI_Old/bin
|
||||||
Data/
|
Data/
|
||||||
|
/WebUI/Libraries
|
||||||
@@ -4,12 +4,6 @@ namespace CppCompatibilityModule.Extern;
|
|||||||
|
|
||||||
public static class Delegates
|
public static class Delegates
|
||||||
{
|
{
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate void ProcessObject(ref object obj);
|
|
||||||
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate void ExecuteDelegateFunction();
|
|
||||||
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
public delegate void SetExternFunctionPointerDelegate(IntPtr funcPtr);
|
public delegate void SetExternFunctionPointerDelegate(IntPtr funcPtr);
|
||||||
|
|
||||||
|
|||||||
@@ -116,23 +116,6 @@ namespace CppCompatibilityModule.Extern
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CallFunction(string methodName, ref object parameter)
|
|
||||||
{
|
|
||||||
var functionDelegate = GetDelegateForFunctionPointer<Delegates.ProcessObject>(methodName);
|
|
||||||
|
|
||||||
functionDelegate(ref parameter);
|
|
||||||
|
|
||||||
_Logger.Log($"Function {methodName} called successfully with parameter");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CallFunction(string methodName)
|
|
||||||
{
|
|
||||||
var functionDelegate = GetDelegateForFunctionPointer<Delegates.ExecuteDelegateFunction>(methodName);
|
|
||||||
|
|
||||||
functionDelegate();
|
|
||||||
|
|
||||||
_Logger.Log($"Function {methodName} called successfully");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,24 +17,14 @@ public class ExternalApplication
|
|||||||
this._Logger = logger;
|
this._Logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void CallFunction(string methodName, ref object parameter)
|
|
||||||
{
|
|
||||||
_ExternLibrary.CallFunction(methodName, ref parameter);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void CallFunction(string methodName)
|
|
||||||
{
|
|
||||||
_ExternLibrary.CallFunction(methodName);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal T GetDelegateForFunctionPointer<T>(string methodName) where T : Delegate
|
internal T GetDelegateForFunctionPointer<T>(string methodName) where T : Delegate
|
||||||
{
|
{
|
||||||
return _ExternLibrary.GetDelegateForFunctionPointer<T>(methodName);
|
return _ExternLibrary.GetDelegateForFunctionPointer<T>(methodName);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void SetExternFunctionToPointToFunction(string externalFunctionName, Delegates.CsharpFunctionDelegate localFunction)
|
internal object? SetExternFunctionToPointToFunction<TLocalFunctionDelegate>(string externalFunctionName, TLocalFunctionDelegate localFunction) where TLocalFunctionDelegate : Delegate
|
||||||
{
|
{
|
||||||
_ExternLibrary.SetExternFunctionSetterPointerToCustomDelegate<Delegates.SetExternFunctionPointerDelegate, Delegates.CsharpFunctionDelegate>(externalFunctionName, localFunction);
|
return _ExternLibrary.SetExternFunctionSetterPointerToCustomDelegate<Delegates.SetExternFunctionPointerDelegate, TLocalFunctionDelegate>(externalFunctionName, localFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void FreeLibrary()
|
internal void FreeLibrary()
|
||||||
|
|||||||
@@ -43,25 +43,26 @@ public class ExternalApplicationHandler
|
|||||||
_ExternalApplicationManager.FreeApplication(applicationId);
|
_ExternalApplicationManager.FreeApplication(applicationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CallFunctionWithParameter(Guid appId, string functionName, ref object parameter)
|
public T GetFunctionDelegate<T>(Guid applicationId, string functionName) where T : Delegate
|
||||||
{
|
{
|
||||||
if (_ExternalApplicationManager is null)
|
if (_ExternalApplicationManager is null)
|
||||||
{
|
{
|
||||||
_Logger.Log("Failed to call function because the manager is not initialized. This should have never happened in the first place!!!", this, LogType.Critical);
|
_Logger.Log("Failed to get function delegate because the manager is not initialized. This should have never happened in the first place!!!", this, LogType.Critical);
|
||||||
return;
|
return default!;
|
||||||
}
|
}
|
||||||
|
|
||||||
_ExternalApplicationManager.ExecuteApplicationFunctionWithParameter(appId, functionName, ref parameter);
|
return _ExternalApplicationManager.GetFunctionDelegate<T>(applicationId, functionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CallFunctionWithoutParameter(Guid appId, string functionName)
|
public object? SetExternFunctionToPointToFunction<TLocalFunctionDelegate>(Guid applicationId, string functionName,
|
||||||
|
TLocalFunctionDelegate localFunction) where TLocalFunctionDelegate : Delegate
|
||||||
{
|
{
|
||||||
if (_ExternalApplicationManager is null)
|
if(_ExternalApplicationManager is null)
|
||||||
{
|
{
|
||||||
_Logger.Log("Failed to call function because the manager is not initialized. This should have never happened in the first place!!!", this, LogType.Critical);
|
_Logger.Log("Failed to set external function pointer because the manager is not initialized. This should have never happened in the first place!!!", this, LogType.Critical);
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_ExternalApplicationManager.ExecuteApplicationFunctionWithoutParameter(appId, functionName);
|
return _ExternalApplicationManager.SetExternFunctionToPointToFunction(applicationId, functionName, localFunction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,30 +46,28 @@ internal class ExternalApplicationManager
|
|||||||
_Logger.Log($"Application with id {applicationId} freed successfully");
|
_Logger.Log($"Application with id {applicationId} freed successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ExecuteApplicationFunctionWithParameter(Guid appId, string functionName, ref object parameter)
|
public T GetFunctionDelegate<T>(Guid applicationId, string functionName) where T : Delegate
|
||||||
{
|
{
|
||||||
var application = _ExternalApplications.FirstOrDefault(app => app.ApplicationId == appId);
|
var application = _ExternalApplications.FirstOrDefault(app => app.ApplicationId == applicationId, null);
|
||||||
if(application is null)
|
if(application is null)
|
||||||
{
|
{
|
||||||
_Logger.Log($"Couldn't find application with id {appId}");
|
_Logger.Log($"Couldn't find application with id {applicationId}");
|
||||||
return;
|
return default!;
|
||||||
}
|
}
|
||||||
|
|
||||||
application.CallFunction(functionName, ref parameter);
|
return application.GetDelegateForFunctionPointer<T>(functionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ExecuteApplicationFunctionWithoutParameter(Guid appId, string functionName)
|
public object? SetExternFunctionToPointToFunction<TLocalFunctionDelegate>(Guid applicationId, string externalFunctionName, TLocalFunctionDelegate localFunction) where TLocalFunctionDelegate : Delegate
|
||||||
{
|
{
|
||||||
var application = _ExternalApplications.FirstOrDefault(app => app.ApplicationId == appId);
|
var application = _ExternalApplications.FirstOrDefault(app => app.ApplicationId == applicationId, null);
|
||||||
if(application is null)
|
if(application is null)
|
||||||
{
|
{
|
||||||
_Logger.Log($"Couldn't find application with id {appId}");
|
_Logger.Log($"Couldn't find application with id {applicationId}");
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
application.CallFunction(functionName);
|
return application.SetExternFunctionToPointToFunction<TLocalFunctionDelegate>(externalFunctionName, localFunction);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
14
Plugins/CppModuleDemo/CppModuleDemo.csproj
Normal file
14
Plugins/CppModuleDemo/CppModuleDemo.csproj
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\DiscordBotCore.PluginCore\DiscordBotCore.PluginCore.csproj" />
|
||||||
|
<ProjectReference Include="..\..\Modules\CppCompatibilityModule\CppCompatibilityModule.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
9
Plugins/CppModuleDemo/Delegates.cs
Normal file
9
Plugins/CppModuleDemo/Delegates.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace CppModuleDemo;
|
||||||
|
|
||||||
|
public static class Delegates
|
||||||
|
{
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
public delegate void ModifyComplexObject(ref ExampleComplexObject obj);
|
||||||
|
}
|
||||||
19
Plugins/CppModuleDemo/ExampleComplexObject.cs
Normal file
19
Plugins/CppModuleDemo/ExampleComplexObject.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace CppModuleDemo;
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||||
|
public struct ExampleComplexObject
|
||||||
|
{
|
||||||
|
public int IntegerValue;
|
||||||
|
public double DoubleValue;
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||||
|
public string StringValue;
|
||||||
|
|
||||||
|
public ExampleComplexObject(int integerValue, double doubleValue, string stringValue)
|
||||||
|
{
|
||||||
|
IntegerValue = integerValue;
|
||||||
|
DoubleValue = doubleValue;
|
||||||
|
StringValue = stringValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
10
Plugins/CppModuleDemo/InternalSettings.cs
Normal file
10
Plugins/CppModuleDemo/InternalSettings.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using CppCompatibilityModule;
|
||||||
|
using CppCompatibilityModule.Extern;
|
||||||
|
|
||||||
|
namespace CppModuleDemo;
|
||||||
|
|
||||||
|
internal static class InternalSettings
|
||||||
|
{
|
||||||
|
internal static ExternalApplicationHandler? ExternalApplicationHandler { get; set; } = null;
|
||||||
|
internal static Guid DemoModuleInternalId { get; set; } = Guid.Empty;
|
||||||
|
}
|
||||||
78
Plugins/CppModuleDemo/ModuleSlashCommand.cs
Normal file
78
Plugins/CppModuleDemo/ModuleSlashCommand.cs
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
using Discord;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using DiscordBotCore.Logging;
|
||||||
|
using DiscordBotCore.PluginCore.Interfaces;
|
||||||
|
|
||||||
|
namespace CppModuleDemo;
|
||||||
|
|
||||||
|
public class ModuleSlashCommand : IDbSlashCommand
|
||||||
|
{
|
||||||
|
public string Name => "cpp-module-demo";
|
||||||
|
public string Description => "A demo command to showcase the C++ module integration with Discord Bot Core.";
|
||||||
|
public bool CanUseDm => false;
|
||||||
|
public bool HasInteraction => false;
|
||||||
|
|
||||||
|
public List<SlashCommandOptionBuilder> Options => new List<SlashCommandOptionBuilder>()
|
||||||
|
{
|
||||||
|
new SlashCommandOptionBuilder()
|
||||||
|
{
|
||||||
|
Name = "example-integer-value", Description = "An example integer value",
|
||||||
|
Type = ApplicationCommandOptionType.Integer, IsRequired = true
|
||||||
|
},
|
||||||
|
new SlashCommandOptionBuilder()
|
||||||
|
{
|
||||||
|
Name = "example-number-value", Description = "An example number value",
|
||||||
|
Type = ApplicationCommandOptionType.Number, IsRequired = true
|
||||||
|
},
|
||||||
|
new SlashCommandOptionBuilder()
|
||||||
|
{
|
||||||
|
Name = "example-string-value", Description = "An example boolean value",
|
||||||
|
Type = ApplicationCommandOptionType.String, IsRequired = true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public async void ExecuteServer(ILogger logger, SocketSlashCommand context)
|
||||||
|
{
|
||||||
|
long integerValue = (long)context.Data.Options.First(option => option.Name == "example-integer-value").Value;
|
||||||
|
double numberValue = (double)context.Data.Options.First(option => option.Name == "example-number-value").Value;
|
||||||
|
string stringValue = (string)context.Data.Options.First(option => option.Name == "example-string-value").Value;
|
||||||
|
|
||||||
|
if(integerValue > int.MaxValue || integerValue < int.MinValue)
|
||||||
|
{
|
||||||
|
await context.Channel.SendMessageAsync("The provided integer value is out of range. Please provide a valid integer.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.RespondAsync("Processing your request...", ephemeral: true);
|
||||||
|
|
||||||
|
await context.Channel.SendMessageAsync("CppModuleDemo invoked with: \n" +
|
||||||
|
$"Integer Value: {integerValue}\n" +
|
||||||
|
$"Number Value: {numberValue}\n" +
|
||||||
|
$"String Value: {stringValue}");
|
||||||
|
|
||||||
|
ExampleComplexObject complexObject = new ExampleComplexObject
|
||||||
|
{
|
||||||
|
IntegerValue = (int)integerValue,
|
||||||
|
DoubleValue = numberValue,
|
||||||
|
StringValue = stringValue
|
||||||
|
};
|
||||||
|
|
||||||
|
Delegates.ModifyComplexObject? modifyComplexObject =
|
||||||
|
InternalSettings.ExternalApplicationHandler?.GetFunctionDelegate<Delegates.ModifyComplexObject>(
|
||||||
|
InternalSettings.DemoModuleInternalId, "modifyComplexObject");
|
||||||
|
|
||||||
|
if (modifyComplexObject is null)
|
||||||
|
{
|
||||||
|
await context.Channel.SendMessageAsync("Failed to retrieve the C++ function delegate. Please check the C++ module integration.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
modifyComplexObject(ref complexObject);
|
||||||
|
|
||||||
|
await context.Channel.SendMessageAsync("CppModuleDemo command executed successfully! New values are:\n" +
|
||||||
|
$"Integer Value: {((ExampleComplexObject)complexObject).IntegerValue}\n" +
|
||||||
|
$"Number Value: {((ExampleComplexObject)complexObject).DoubleValue}\n" +
|
||||||
|
$"String Value: {((ExampleComplexObject)complexObject).StringValue}");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
31
Plugins/CppModuleDemo/StartupEvent.cs
Normal file
31
Plugins/CppModuleDemo/StartupEvent.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using CppCompatibilityModule;
|
||||||
|
using CppCompatibilityModule.Extern;
|
||||||
|
using DiscordBotCore.PluginCore.Helpers.Execution.DbEvent;
|
||||||
|
using DiscordBotCore.PluginCore.Interfaces;
|
||||||
|
|
||||||
|
namespace CppModuleDemo;
|
||||||
|
|
||||||
|
public class StartupEvent : IDbEvent
|
||||||
|
{
|
||||||
|
public string Name => "CppModuleDemoStartupEvent";
|
||||||
|
public string Description => "A demo event to showcase the C++ module integration with Discord Bot Core on startup.";
|
||||||
|
|
||||||
|
private static string _DllModule = "libCppModuleDemo.dylib";
|
||||||
|
|
||||||
|
public void Start(IDbEventExecutingArgument args)
|
||||||
|
{
|
||||||
|
args.PluginBaseDirectory.Create();
|
||||||
|
InternalSettings.ExternalApplicationHandler = new ExternalApplicationHandler(args.Logger);
|
||||||
|
string fullPath = Path.Combine(args.PluginBaseDirectory.FullName, _DllModule);
|
||||||
|
Guid id = InternalSettings.ExternalApplicationHandler.CreateApplication(fullPath);
|
||||||
|
|
||||||
|
if (id == Guid.Empty)
|
||||||
|
{
|
||||||
|
args.Logger.Log("Failed to create the C++ module application. Please check the DLL path and ensure it is correct.", this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
args.Logger.Log($"CppModuleDemo started successfully with application ID: {id}", this);
|
||||||
|
InternalSettings.DemoModuleInternalId = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
37
Plugins/CppModuleDemo/StopSlashCommand.cs
Normal file
37
Plugins/CppModuleDemo/StopSlashCommand.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using Discord;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using DiscordBotCore.Logging;
|
||||||
|
using DiscordBotCore.PluginCore.Interfaces;
|
||||||
|
|
||||||
|
namespace CppModuleDemo;
|
||||||
|
|
||||||
|
public class StopSlashCommand : IDbSlashCommand
|
||||||
|
{
|
||||||
|
public string Name => "stop-cpp-module-demo";
|
||||||
|
public string Description => "Stops the C++ module demo and cleans up resources.";
|
||||||
|
public bool CanUseDm => false;
|
||||||
|
public bool HasInteraction => false;
|
||||||
|
public List<SlashCommandOptionBuilder> Options => [];
|
||||||
|
|
||||||
|
public async void ExecuteServer(ILogger logger, SocketSlashCommand context)
|
||||||
|
{
|
||||||
|
if (InternalSettings.ExternalApplicationHandler == null)
|
||||||
|
{
|
||||||
|
logger.Log("No C++ module is currently running.", this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Guid id = InternalSettings.DemoModuleInternalId;
|
||||||
|
if (id == Guid.Empty)
|
||||||
|
{
|
||||||
|
logger.Log("No valid C++ module ID found. Cannot stop the module.", this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
InternalSettings.ExternalApplicationHandler.StopApplication(id);
|
||||||
|
InternalSettings.DemoModuleInternalId = Guid.Empty;
|
||||||
|
logger.Log("CppModuleDemo stopped successfully.", this);
|
||||||
|
|
||||||
|
await context.Channel.SendMessageAsync("CppModuleDemo has been stopped and resources cleaned up.");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,9 +5,6 @@ MinimumVisualStudioVersion = 10.0.40219.1
|
|||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiscordBotCore", "DiscordBotCore\DiscordBotCore.csproj", "{5A99BFC3-EB39-4AEF-8D61-3CE22D013B02}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiscordBotCore", "DiscordBotCore\DiscordBotCore.csproj", "{5A99BFC3-EB39-4AEF-8D61-3CE22D013B02}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{5CF9AD7B-6BF0-4035-835F-722F989C01E1}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{5CF9AD7B-6BF0-4035-835F-722F989C01E1}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
|
||||||
Plugins\README.md = Plugins\README.md
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{EA4FA308-7B2C-458E-8485-8747D745DD59}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{EA4FA308-7B2C-458E-8485-8747D745DD59}"
|
||||||
EndProject
|
EndProject
|
||||||
@@ -41,6 +38,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests.DiscordBotCore.Loggin
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests.DiscordBotCore.Configuration", "Tests\Tests.DiscordBotCore.Configuration\Tests.DiscordBotCore.Configuration.csproj", "{52C59C73-C23C-4608-8827-383577DEB8D8}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests.DiscordBotCore.Configuration", "Tests\Tests.DiscordBotCore.Configuration\Tests.DiscordBotCore.Configuration.csproj", "{52C59C73-C23C-4608-8827-383577DEB8D8}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CppModuleDemo", "Plugins\CppModuleDemo\CppModuleDemo.csproj", "{55425935-456E-4ED4-9283-2CB6A6C7AC7D}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -231,6 +230,18 @@ Global
|
|||||||
{52C59C73-C23C-4608-8827-383577DEB8D8}.Release|ARM64.Build.0 = Release|Any CPU
|
{52C59C73-C23C-4608-8827-383577DEB8D8}.Release|ARM64.Build.0 = Release|Any CPU
|
||||||
{52C59C73-C23C-4608-8827-383577DEB8D8}.Release|x64.ActiveCfg = Release|Any CPU
|
{52C59C73-C23C-4608-8827-383577DEB8D8}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
{52C59C73-C23C-4608-8827-383577DEB8D8}.Release|x64.Build.0 = Release|Any CPU
|
{52C59C73-C23C-4608-8827-383577DEB8D8}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{55425935-456E-4ED4-9283-2CB6A6C7AC7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{55425935-456E-4ED4-9283-2CB6A6C7AC7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{55425935-456E-4ED4-9283-2CB6A6C7AC7D}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||||
|
{55425935-456E-4ED4-9283-2CB6A6C7AC7D}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||||
|
{55425935-456E-4ED4-9283-2CB6A6C7AC7D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{55425935-456E-4ED4-9283-2CB6A6C7AC7D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{55425935-456E-4ED4-9283-2CB6A6C7AC7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{55425935-456E-4ED4-9283-2CB6A6C7AC7D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{55425935-456E-4ED4-9283-2CB6A6C7AC7D}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||||
|
{55425935-456E-4ED4-9283-2CB6A6C7AC7D}.Release|ARM64.Build.0 = Release|Any CPU
|
||||||
|
{55425935-456E-4ED4-9283-2CB6A6C7AC7D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{55425935-456E-4ED4-9283-2CB6A6C7AC7D}.Release|x64.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@@ -241,6 +252,7 @@ Global
|
|||||||
{9A4B98C1-00AC-481C-BE55-A70C0B9D3BE7} = {5CF9AD7B-6BF0-4035-835F-722F989C01E1}
|
{9A4B98C1-00AC-481C-BE55-A70C0B9D3BE7} = {5CF9AD7B-6BF0-4035-835F-722F989C01E1}
|
||||||
{94238D37-60C6-4E40-80EC-4B4D242F5914} = {8F27B3EA-F292-40DF-B9B3-4B0E6BEA4E70}
|
{94238D37-60C6-4E40-80EC-4B4D242F5914} = {8F27B3EA-F292-40DF-B9B3-4B0E6BEA4E70}
|
||||||
{52C59C73-C23C-4608-8827-383577DEB8D8} = {8F27B3EA-F292-40DF-B9B3-4B0E6BEA4E70}
|
{52C59C73-C23C-4608-8827-383577DEB8D8} = {8F27B3EA-F292-40DF-B9B3-4B0E6BEA4E70}
|
||||||
|
{55425935-456E-4ED4-9283-2CB6A6C7AC7D} = {5CF9AD7B-6BF0-4035-835F-722F989C01E1}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {3FB3C5DE-ED21-4D2E-ABDD-3A00EE4A2FFF}
|
SolutionGuid = {3FB3C5DE-ED21-4D2E-ABDD-3A00EE4A2FFF}
|
||||||
|
|||||||
@@ -65,6 +65,7 @@
|
|||||||
var buffer = new byte[file.Size];
|
var buffer = new byte[file.Size];
|
||||||
await file.OpenReadStream().ReadAsync(buffer);
|
await file.OpenReadStream().ReadAsync(buffer);
|
||||||
_message = $"Uploaded file: {file.Name} ({file.Size} bytes)";
|
_message = $"Uploaded file: {file.Name} ({file.Size} bytes)";
|
||||||
|
selectedFile = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task HandleValidSubmit()
|
private async Task HandleValidSubmit()
|
||||||
|
|||||||
@@ -1,7 +1,71 @@
|
|||||||
|
using System.Reflection;
|
||||||
using WebUI;
|
using WebUI;
|
||||||
using WebUI.Services;
|
using WebUI.Services;
|
||||||
using WebUI.Components;
|
using WebUI.Components;
|
||||||
|
|
||||||
|
#region Load External (Unmanaged) Assemblies
|
||||||
|
|
||||||
|
// This code is used to load external (unmanaged) assemblies from the same folder as the executing assembly.
|
||||||
|
// It handles the AssemblyResolve event to search for the requested assembly in a specific folder structure.
|
||||||
|
// The folder structure is expected to be: <ExecutingAssemblyDirectory>/Libraries/<RequestingAssemblyName>/<AssemblyName>.<Extension>
|
||||||
|
// The extensions to search for are specified in the 'extensions' parameter.
|
||||||
|
|
||||||
|
var currentDomain = AppDomain.CurrentDomain;
|
||||||
|
currentDomain.AssemblyResolve += (sender, args) => LoadFromSameFolder(sender,args, [".dll", ".so", ".dylib"]);
|
||||||
|
|
||||||
|
static Assembly? LoadFromSameFolder(object? sender, ResolveEventArgs args, string[] extensions)
|
||||||
|
{
|
||||||
|
string? requestingAssemblyName = args.RequestingAssembly?.GetName().Name;
|
||||||
|
string executingAssemblyLocation = Assembly.GetExecutingAssembly().Location;
|
||||||
|
string? executingAssemblyDirectory = Path.GetDirectoryName(executingAssemblyLocation);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(executingAssemblyDirectory))
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Error: Could not determine the directory of the executing assembly.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
string librariesFolder = Path.Combine(executingAssemblyDirectory, "Libraries", requestingAssemblyName ?? "");
|
||||||
|
string requestedAssemblyNameWithoutExtension = new AssemblyName(args.Name).Name;
|
||||||
|
|
||||||
|
Console.WriteLine($"Requesting Assembly: {requestingAssemblyName}");
|
||||||
|
Console.WriteLine($"Requested Assembly Name (without extension): {requestedAssemblyNameWithoutExtension}");
|
||||||
|
Console.WriteLine($"Searching in folder: {librariesFolder}");
|
||||||
|
Console.WriteLine($"Searching for extensions: {string.Join(", ", extensions)}");
|
||||||
|
|
||||||
|
foreach (string extension in extensions)
|
||||||
|
{
|
||||||
|
string assemblyFileName = requestedAssemblyNameWithoutExtension + extension;
|
||||||
|
string assemblyPath = Path.Combine(librariesFolder, assemblyFileName);
|
||||||
|
|
||||||
|
Console.WriteLine($"Attempting to load from: {assemblyPath}");
|
||||||
|
|
||||||
|
if (File.Exists(assemblyPath))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var fileAssembly = Assembly.LoadFrom(assemblyPath);
|
||||||
|
Console.WriteLine($"Successfully loaded Assembly: {fileAssembly.FullName}");
|
||||||
|
return fileAssembly;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Error loading assembly from '{assemblyPath}': {ex.Message}");
|
||||||
|
// Optionally log the full exception for debugging
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"File not found: {assemblyPath}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"Failed to load assembly '{args.Name}' from the specified locations.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
// Add services to the container.
|
// Add services to the container.
|
||||||
|
|||||||
Reference in New Issue
Block a user