Install
openclaw skills install @lindexi/easinote-native-plugin-development创建、修改、排查、调试和打包希沃白板 EasiNote 5 原生插件的开发指南。只要用户提到希沃白板插件、EasiPlugin、dotnetCampus.EasiPlugin.Sdk、EasiNote 原生插件、EN.EditingBoardApi、BoardEditMenuItem、HeadToolBarItem、学科工具、IUIItemManager、Container.GetAsync、SafeWindow、Cvte.EasiUI、GurnetUI,或需要安全退出、重启 EasiNote、扩展备课/授课/云课件界面,就应使用此技能;即使用户没有明确要求使用技能,也应在项目搭建、生命周期、
openclaw skills install @lindexi/easinote-native-plugin-development使用 dotnetCampus.EasiPlugin.Sdk 创建加载到希沃白板 EasiNote 5 进程内的 .NET 6/WPF 原生插件。插件可调用宿主类型和成员,但实现前必须先识别运行端、真实就绪条件、UI 线程要求和目标宿主版本。
.csproj、插件入口、相关 UI Item、资源和调试配置。仅加载当前任务需要的文档:
.csproj、配置宿主调试或理解安装产物:读取 references/project-setup.md。GetAsync<T>、Dispatcher、Ready 或重复注册问题:读取 references/lifecycle-and-container.md。HeadToolBarItem、顶部工具栏或“学科工具”下拉入口,处理 Key、图标和 Tooltip:读取 references/head-toolbar-and-subject-tools.md。SafeWindow、EasiUI/GurnetUI 样式或语义资源:读取 references/wpf-visual-integration.md。使用 EN.CommandOptions.IsCloud 区分 Cloud 与 Shell。IsCloud == false 只表示 Shell;只有业务确实需要时,再通过 EN.App.CurrentMode 区分 Edit 与 Display。
先明确功能运行在 Cloud、Shell Edit、Shell Display,还是两端分别执行不同逻辑。在 OnRunningAsync 中做 Cloud/Shell 职责分流,不跨端访问服务、ViewModel、画板或 UI。
自动扫描插件程序集不等于进程隔离。Shell 专属 UI Item 若依赖 Shell 服务或资源,应在 Shell 分支显式注册。
不要把“插件已加载”“应用 Ready”和“目标服务已注册”视为同一件事。
如果后续工作依赖某个容器服务,优先直接等待:
var service = await Container.Current
.GetAsync<TService>()
.ConfigureAwait(false);
不要机械叠加固定延迟、EN.App.Ready、轮询、自定义状态机或 Interlocked。只有已从调用语义确认存在额外前置条件、重复调用或并发重入时,才增加对应机制。
GetAsync<T> 解决服务何时可用,不保证后续代码位于 WPF UI 线程。正确顺序通常是:
Application.Current.Dispatcher;Lang.Sources 和注册 UI Item。不要为了“保证时机”在 Dispatcher 中同步调用 Container.Current.Get<T>()。
通过 IUIItemManager.Append 注册与场景匹配的 UI Item:
BoardEditMenuItem + UIItemPurposes.BoardEditMenu:备课画板右键菜单;HeadToolBarItem + UIItemPurposes.HeadToolBar:备课顶部工具栏体系及“学科工具”下拉;[UIItem] 自动扫描和 Append 动态注册二选一,不能同时使用。Key 必须稳定且唯一;Predicate 必须表达真实业务条件,不要复制占位逻辑。
界面可见字符串优先通过 Lang.Sources 注册,并使用宿主实际读取的语言键。WPF 图片或样式资源必须在使用它们的 UI Item 或窗口实例化前可用。
宿主资源、语言键和内部样式可能存在版本差异。遇到资源不存在时,应检查目标版本和同类宿主界面的实际用法,不虚构兼容键。
根据模式选择 API:
EN.EditingBoardApi.CurrentSlide;EN.EditingBoardApi.Slides;EN.DisplayingBoardApi.CurrentSlide。使用 OfType<T>() 筛选元素并显式处理未找到的情况。组合元素可能包含内部 Elements;是否递归应依据实际数据模型。修改坐标前区分 Slide 坐标与元素内部坐标。
耗时工作异步执行并传递 CancellationToken。不要在 UI 线程执行长时间 CPU 或 I/O 操作,不要 fire-and-forget 后丢失异常。
如果宿主入口只能使用同步返回或 async void 回调,应建立明确的异常观察路径,避免未处理异常终止宿主进程。
通过 <UseEasiNote> 控制自动引用范围:none、api、core、most、all。选择满足编译的最小级别。仅缺少单个宿主程序集时,优先使用 SDK 的 EasiNoteReference,不要直接扩大到 all。
EasiNote.exe 配置调试,不提交开发机版本目录。catch。