2024-11-08 17:30:51 +08:00
|
|
|
|
using Serein.Library;
|
|
|
|
|
|
using Serein.Library.Utils;
|
|
|
|
|
|
using System;
|
2024-11-02 16:48:40 +08:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Serein.NodeFlow.Tool
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
internal class NativeDllHelper
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
// 引入 Windows API 函数
|
|
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
|
|
|
|
private static extern IntPtr LoadLibrary(string lpFileName);
|
|
|
|
|
|
|
|
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
|
|
|
|
private static extern bool FreeLibrary(IntPtr hModule);
|
|
|
|
|
|
|
|
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
|
|
|
|
private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 引入 Unix/Linux 的动态库加载函数
|
|
|
|
|
|
[DllImport("libdl.so.2", SetLastError = true)]
|
|
|
|
|
|
private static extern IntPtr dlopen(string filename, int flag);
|
|
|
|
|
|
|
|
|
|
|
|
[DllImport("libdl.so.2", SetLastError = true)]
|
|
|
|
|
|
private static extern IntPtr dlsym(IntPtr handle, string symbol);
|
|
|
|
|
|
|
|
|
|
|
|
[DllImport("libdl.so.2", SetLastError = true)]
|
|
|
|
|
|
private static extern int dlclose(IntPtr handle);
|
|
|
|
|
|
|
|
|
|
|
|
private const int RTLD_NOW = 2;
|
|
|
|
|
|
|
|
|
|
|
|
// bool LoadDll(string file)
|
|
|
|
|
|
// void LoadAllDll(string path, bool isRecurrence = true);
|
|
|
|
|
|
|
|
|
|
|
|
private static List<IntPtr> Nints = new List<nint>();
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 加载单个Dll
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="file"></param>
|
|
|
|
|
|
public static bool LoadDll(string file)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
|
|
|
|
|
{
|
|
|
|
|
|
return LoadWindowsLibrarie(file);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
|
|
|
|
|
{
|
|
|
|
|
|
return LoadLinuxLibrarie(file);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2024-11-08 17:30:51 +08:00
|
|
|
|
SereinEnv.WriteLine(InfoType.ERROR, "非预期的OS系统");
|
2024-11-02 16:48:40 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static void LoadAllDll(string path, bool isRecurrence = true)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
|
|
|
|
|
{
|
2025-05-27 18:32:40 +08:00
|
|
|
|
if (!Directory.Exists(path))
|
|
|
|
|
|
{
|
|
|
|
|
|
SereinEnv.WriteLine(InfoType.ERROR, $"尝试加载Dll时失败,路径不存在。{path}");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-11-02 16:48:40 +08:00
|
|
|
|
foreach (var file in Directory.GetFiles(path, "*.dll"))
|
|
|
|
|
|
{
|
|
|
|
|
|
LoadWindowsLibrarie(file);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var file in Directory.GetFiles(path, "*.so"))
|
|
|
|
|
|
{
|
|
|
|
|
|
LoadLinuxLibrarie(file);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2024-11-08 17:30:51 +08:00
|
|
|
|
SereinEnv.WriteLine(InfoType.ERROR, "非预期的OS系统");
|
2024-11-02 16:48:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var dir in Directory.GetDirectories(path))
|
|
|
|
|
|
{
|
|
|
|
|
|
LoadAllDll(dir, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 加载Windows类库
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="path"></param>
|
|
|
|
|
|
/// <param name="isRecurrence">是否递归加载</param>
|
|
|
|
|
|
private static bool LoadWindowsLibrarie(string file)
|
|
|
|
|
|
{
|
|
|
|
|
|
IntPtr hModule = IntPtr.Zero;
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
hModule = LoadLibrary(file);
|
|
|
|
|
|
// 加载 DLL
|
|
|
|
|
|
if (hModule != IntPtr.Zero)
|
|
|
|
|
|
{
|
|
|
|
|
|
Nints.Add(hModule);
|
2024-11-08 17:30:51 +08:00
|
|
|
|
SereinEnv.WriteLine(InfoType.INFO, $"Loaded: {file}");
|
2024-11-02 16:48:40 +08:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2024-11-08 17:30:51 +08:00
|
|
|
|
SereinEnv.WriteLine(InfoType.INFO, $"Failed to load {file}: {Marshal.GetLastWin32Error()}");
|
2024-11-02 16:48:40 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
2024-11-08 17:30:51 +08:00
|
|
|
|
SereinEnv.WriteLine(InfoType.ERROR, $"Error loading {file}: {ex.Message}");
|
2024-11-02 16:48:40 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 加载Linux类库
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="file"></param>
|
|
|
|
|
|
private static bool LoadLinuxLibrarie(string file)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
IntPtr handle = IntPtr.Zero;
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
handle = dlopen(file, RTLD_NOW);
|
|
|
|
|
|
if (handle != IntPtr.Zero)
|
|
|
|
|
|
{
|
|
|
|
|
|
Nints.Add(handle);
|
2024-11-08 17:30:51 +08:00
|
|
|
|
SereinEnv.WriteLine(InfoType.INFO, $"Loaded: {file}");
|
2024-11-02 16:48:40 +08:00
|
|
|
|
return true;
|
|
|
|
|
|
// 可以调用共享库中的函数
|
|
|
|
|
|
// IntPtr procAddress = dlsym(handle, "my_function");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2024-11-08 17:30:51 +08:00
|
|
|
|
SereinEnv.WriteLine(InfoType.INFO, $"Failed to load {file}: {Marshal.GetLastWin32Error()}");
|
2024-11-02 16:48:40 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
2024-11-08 17:30:51 +08:00
|
|
|
|
SereinEnv.WriteLine(InfoType.ERROR, $"Error loading {file}: {ex.Message}");
|
2024-11-02 16:48:40 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 卸载所有已加载DLL
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static void FreeLibrarys()
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = 0; i < Nints.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
IntPtr hModule = Nints[i];
|
|
|
|
|
|
FreeLibrary(hModule);
|
|
|
|
|
|
}
|
|
|
|
|
|
Nints.Clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|