This repository has been archived by the owner on Jun 23, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
如何调用酷Q插件事件
Mr.喜 edited this page Aug 16, 2020
·
2 revisions
酷Q规定,插件dll均需要使用stdcall的形式来暴露各个事件的接口。所以作为启动器的此程序,需要分发事件之后调用这些dll的事件即可
- 插件同名json的json的event字段中保存了此dll使用的所有事件id以及函数名称
- 使用外部程序
- 各种查壳工具 ExeInfoPe、PEId等
- DllExport 命令行:
.\DllExport -pe-exp-list **.dll
参考酷Q官方的易语言插件demo,没有保留的可以来这里下载
可以看到这个私聊函数需要传递五个参数
using Launcher.Sdk.Cqp.Enum;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
namespace DllDemo
{
public class Dll
{
[DllImport("kernel32.dll")]
private extern static IntPtr LoadLibrary(String path);
[DllImport("kernel32.dll")]
private extern static IntPtr GetProcAddress(IntPtr lib, String funcName);
[DllImport("kernel32.dll")]
public extern static int GetLastError();
private IntPtr hLib;
private delegate int Type_PrivateMsg(int subType, int msgId, long fromQQ, IntPtr msg, int font);//这里提供的参数表需要与要调用函数的参数表完全一致
private Type_PrivateMsg PrivateMsg;
public IntPtr Load(string filepath, JObject json)
{
if (hLib == null || hLib == (IntPtr)0)
{
try { hLib = LoadLibrary(filepath); }
catch
{
Console.WriteLine($"Error,插件 {filepath} 载入失败,LoadLibrary :GetLastError={GetLastError()}");//0表示正常,126表示缺少依赖等等
}
}
if (hLib != (IntPtr)0)
{
PrivateMsg = (Type_PrivateMsg)Invoke("_eventPrivateMsg", typeof(Type_PrivateMsg));//使用特定的函数名寻找函数,这个名字可以使用变量实现动态变化
return hLib;
}
return (IntPtr)0;
}
//将要执行的函数转换为委托
public Delegate Invoke(string APIName, Type t)
{
IntPtr api = GetProcAddress(hLib, APIName);
if (api == (IntPtr)0)
return null;
return Marshal.GetDelegateForFunctionPointer(api, t);
}
//调用库中事件
public int CallFunction(string ApiName, params object[] args)//外部可以通过这个函数完成对特定函数的调用
{
switch (ApiName)
{
case "PrivateMsg":
return PrivateMsg(Convert.ToInt32(args[0]), Convert.ToInt32(args[1]), Convert.ToInt64(args[2]), (IntPtr)args[3], 1);
default:
Console.WriteLine("未找到或者未实现的事件");
return -1;
}
}
}
}
DLLExport在传递string参数时,需要使用指针也就是IntPtr来进行传递 二者转换的方法如下:
- string转换IntPtr:
IntPtr ptr = Marshal.StringToHGlobalAnsi(str);
- IntPtr转换string:
string str = Marshal.PtrToStringAnsi(ptr);