You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在嵌入的Lua中调用WinRT .NET Framework类型与方法?

在MUSHclient Lua中实现Windows通知:替代外部工具的COM/FFI方案

你当前用os.execute调用外部toast工具的方式确实繁琐,下面提供两种更直接的方案,基于你提到的COM和FFI能力:

方案一:通过luacom调用WinRT COM接口

WinRT的Windows.UI.Notifications.ToastNotificationManager本质是基于COM的,所以可以用luacom直接调用。步骤很清晰:

  1. 初始化COM环境(MUSHclient可能已经做了,但显式调用更稳妥)
  2. 获取Toast通知管理器实例,构造符合Windows要求的XML通知内容
  3. 创建并发送通知

示例代码:

local luacom = require "luacom"

-- 初始化COM
luacom.InitializeCOM()

-- 创建ToastNotificationManager实例
local toastManager = luacom.CreateObject("Windows.UI.Notifications.ToastNotificationManager")
if not toastManager then
  error("没法创建ToastNotificationManager实例")
end

-- 获取通用的通知发送器(用Windows.Default就能正常显示)
local notifier = toastManager:CreateToastNotifier("Windows.Default")

-- 构造Toast的XML内容(必须符合Windows的Toast格式)
local toastXml = [[
<toast>
  <visual>
    <binding template="ToastGeneric">
      <text>MUSHclient通知</text>
      <text>这是Lua脚本发的Toast通知</text>
    </binding>
  </visual>
</toast>
]]

-- 创建XML文档对象并加载内容
local xmlDoc = luacom.CreateObject("Windows.Data.Xml.Dom.XmlDocument")
xmlDoc:LoadXml(toastXml)

-- 创建Toast通知对象并发送
local toast = luacom.CreateObject("Windows.UI.Notifications.ToastNotification", xmlDoc)
notifier:Show(toast)

-- 可选:释放COM资源
luacom.UninitializeCOM()

注意:如果你的MUSHclient版本较旧,luacom可能不支持WinRT COM对象,这时候可以试试下面的FFI方案。

方案二:通过LuaJIT FFI调用Windows API

如果COM方式行不通,用FFI调用原生API也是个选项。如果不需要严格的Toast通知,用系统托盘通知会简单很多;要是一定要Toast,就得手动绑定大量WinRT接口,比较麻烦,这里先给托盘通知的示例:

local ffi = require "ffi"

-- 声明Windows API的结构体和函数
ffi.cdef[[
typedef struct {
  UINT cbSize;
  UINT uFlags;
  HWND hWnd;
  UINT uID;
  HICON hIcon;
  char szTip[128];
  DWORD dwState;
  DWORD dwStateMask;
  char szInfo[256];
  union {
    UINT uTimeout;
    UINT uVersion;
  } DUMMYUNIONNAME;
  char szInfoTitle[64];
  DWORD dwInfoFlags;
  GUID guidItem;
  HICON hBalloonIcon;
} NOTIFYICONDATAA;

BOOL Shell_NotifyIconA(DWORD dwMessage, NOTIFYICONDATAA* pnid);
]]

local shell32 = ffi.load("shell32")

-- 构造通知数据
local nid = ffi.new("NOTIFYICONDATAA")
nid.cbSize = ffi.sizeof(nid)
nid.uFlags = 0x00000010 -- NIF_INFO标记,指定显示气泡信息
nid.szInfoTitle = "MUSHclient托盘通知"
nid.szInfo = "这是Lua脚本发的托盘通知"
nid.dwInfoFlags = 0x00000001 -- 显示信息图标

-- 发送通知(NIM_ADD是添加图标并显示气泡)
shell32.Shell_NotifyIconA(0x00000000, nid)

-- 可选:5秒后删除托盘图标
local function remove_notification()
  shell32.Shell_NotifyIconA(0x00000002, nid) -- NIM_DELETE删除图标
end
utils.timer(5, remove_notification)

方案对比

  • COM方式:完美匹配你想要的ToastNotificationManager,代码直观,能实现标准Windows Toast,但依赖luacom对WinRT的兼容性。
  • FFI方式:灵活性强,但Toast实现复杂度高,托盘通知则简单直接,适合不需要标准Toast的场景。

内容的提问来源于stack exchange,提问作者Danj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 03:54:23