OneNote 插件开发笔记
最近在折腾 OneNote 插件开发,网上的资料特别少,绕了不少弯路,这里总结一下。
目录
- 环境要求
- 项目配置
- 代码规范
- 编译配置
- 注册表配置
- COM 注册步骤
- 常见问题排查
- 调试技巧
环境要求
必需软件
- Visual Studio 2022(带 .NET Framework 4.8 SDK)
- OneNote 桌面版(Office 365/2016/2019/2021)
- .NET Framework 4.8(不能用 .NET Core 或 .NET 5+)
验证 OneNote 版本
OneNote -> File -> Account -> About OneNote
必须显示 32-bit 或 64-bit 桌面版,不能是 UWP 版或 Web 版。
验证 Office 架构
reg query "HKLM\SOFTWARE\Microsoft\Office\ClickToRun\Configuration" /v Platform
输出 x64 或 x86,决定 DLL 编译架构。
项目配置
创建项目
Visual Studio -> Create Project -> Class Library (.NET Framework),选 .NET Framework 4.8。
.csproj 关键配置
<PropertyGroup>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<OutputType>Library</OutputType>
<PlatformTarget>x64</PlatformTarget>
<RegisterForComInterop>false</RegisterForComInterop>
</PropertyGroup>
COM 引用中 EmbedInteropTypes 必须设为 False:
- Extensibility (GUID: AC0714F2-3D04-11D1-AE7D-00A0C90F26F4)
- Microsoft.Office.Core (GUID: 2DF8D04C-5BFA-101B-BDE5-00AA0044DE52)
- Microsoft.Office.Interop.OneNote (GUID: 0EA692EE-BB50-4E3C-AEF0-356D91732725)
AssemblyInfo.cs
[assembly: ComVisible(true)]
[assembly: CLSCompliant(true)]
[assembly: Guid("YOUR-GUID-HERE")]
代码规范
AddIn 主类
using System;
using Extensibility;
using Microsoft.Office.Core;
[ComVisible(true)]
[Guid("YOUR-GUID-HERE")]
[ProgId("YourAddIn.AddIn")]
[ClassInterface(ClassInterfaceType.None)]
public class AddIn : IDTExtensibility2, IRibbonExtensibility
{
public AddIn() { }
public void OnConnection(object Application,
ext_ConnectMode ConnectMode, object AddInInst, ref Array custom) { }
public void OnDisconnection(ext_DisconnectMode RemoveMode, ref Array custom)
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
public void OnAddInsUpdate(ref Array custom) { }
public void OnStartupComplete(ref Array custom) { }
public void OnBeginShutdown(ref Array custom) { }
public string GetCustomUI(string RibbonID)
{
return Properties.Resources.ribbon;
}
}
Ribbon XML
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" loadImage="GetImage">
<ribbon>
<tabs>
<tab idMso="TabHome">
<group id="groupTools" label="Tools">
<button id="btnAction" label="Run" size="large" onAction="OnClick" />
</group>
</tab>
</tabs>
</ribbon>
</customUI>
编译与部署
msbuild YourProject.sln /p:Configuration=Release /p:Platform=x64
New-Item -ItemType Directory -Path "C:\Program Files\YourAddIn" -Force
Copy-Item "bind\Release\*.dll" "C:\Program Files\YourAddIn\" -Force
DLL 必须放 Program Files,用户目录会被 OneNote 拒载。
注册表配置
这是最关键的部分!
DllSurrogate(最重要)
[HKEY_CLASSES_ROOT\AppID\{YOUR-GUID}]
"DllSurrogate"=""
[HKEY_CLASSES_ROOT\CLSID\{YOUR-GUID}]
"AppID"="{YOUR-GUID}"
没有 DllSurrogate,OneNote 会静默拒绝加载 AddIn!
OneNote AddIn 注册表
[HKEY_CURRENT_USER\Software\Microsoft\Office\OneNote\AddIns\YourAddIn.AddIn]
"LoadBehavior"=dword:00000003
"FriendlyName"="YourAddIn"
"Description"="Your AddIn Description"
"CommandLineSafe"=dword:00000001
路径中不能包含版本号(如 16.0)!
COM 注册表
[HKEY_CLASSES_ROOT\CLSID\{YOUR-GUID}\InprocServer32]
@="mscoree.dll"
"ThreadingModel"="Both"
"Class"="YourAddIn.AddIn"
"Assembly"="YourAddIn, Version=1.0.0.0"
"RuntimeVersion"="v4.0.30319"
"CodeBase"="file:///C:/Program Files/YourAddIn/YourAddIn.DLL"
COM 注册步骤
使用 regasm(注意匹配 Office 位数):
# 64 位 Office
$regasm = "C:\Windows\Microsoft.NET\Framework644.0.30319
egasm.exe"
# 反注册 -> 注册(带 /codebase)
& $regasm /unregister $dllPath
& $regasm /codebase /tlb $dllPath
# 添加 DllSurrogate
New-Item -Path "HKCR:\AppID\{YOUR-GUID}" -Force
New-ItemProperty -Path "HKCR:\AppID\{YOUR-GUID}" -Name "DllSurrogate" -Value "" -Force
New-ItemProperty -Path "HKCR:\CLSID\{YOUR-GUID}" -Name "AppID" -Value "{YOUR-GUID}" -Force
# 设置 OneNote AddIn
$path = "HKCU:\Software\Microsoft\Office\OneNote\AddIns\YourAddIn.AddIn"
New-Item -Path $path -Force
New-ItemProperty -Path $path -Name "LoadBehavior" -Value 3 -PropertyType DWord -Force
New-ItemProperty -Path $path -Name "FriendlyName" -Value "YourAddIn" -Force
New-ItemProperty -Path $path -Name "CommandLineSafe" -Value 1 -PropertyType DWord -Force
验证:
reg query "HKCR\CLSID\{YOUR-GUID}" /s
$com = New-Object -ComObject "YourAddIn.AddIn"
常见问题排查
AddIn 不显示
| 原因 | 方案 |
|---|---|
| 缺少 DllSurrogate | 添加 DllSurrogate 注册表项 |
| 路径含版本号 | 去掉 16.0 等版本号 |
| regasm 位数错 | x64 Office 用 Framework64 |
| DLL 在用户目录 | 移到 Program Files |
LoadBehavior 3 -> 2
说明 OneNote 尝试加载但失败了。检查:
- Fusion 日志 (C:\FusionLogs)
- 事件查看器 (Windows Logs -> Application)
- DLL 依赖是否完整
代码签名
$cert = New-SelfSignedCertificate -Type CodeSigning -Subject "CN=Dev"
signtool.exe sign /a /fd SHA256 /tr http://timestamp.digicert.com "YourAddIn.dll"
调试技巧
Fusion 日志
reg add "HKLM\SOFTWARE\Microsoft\Fusion" /v EnableLog /t REG_DWORD /d 1 /f
reg add "HKLM\SOFTWARE\Microsoft\Fusion" /v LogPath /t REG_SZ /d "C:\FusionLogs" /f
内嵌日志
private static void Log(string msg) {
File.AppendAllText(Path.Combine(Path.GetTempPath(), "AddIn.log"),
$"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {msg}
");
}
快速参考清单
| 阶段 | 检查项 |
|---|---|
| 编译前 | .NET 4.8, x64/x86, ComVisible=true, ClassInterface=None |
| 编译后 | DLL->Program Files, Everyone Read, 代码签名 |
| 注册时 | 正确 regasm, /codebase, DllSurrogate, LoadBehavior=3 |
| 测试前 | 关 OneNote, 清 Wow6432Node, 验证 COM 创建 |
评论列表: