第 ③ 章 · 进入 Windows 11 主右键菜单(MSIX / 稀疏包)
不改一行处理器代码,用稀疏包(sparse package)给第②章的 IExplorerCommand 赋予“包标识”,把命令送进 Win11 的新版主右键菜单;含 AppxManifest、嵌入标识清单、自签名与注册的完整流程。
前两章的命令,在 Windows 11 上都只能在「显示更多选项」的旧菜单里找到。因为 Win11 的新版主菜单有个硬门槛:命令必须来自一个有“包标识”(package identity)的应用,并用 IExplorerCommand + 包清单声明。
好消息是:不用重写处理器。本章把第 ② 章那个 IExplorerCommand 原样拿来,套一层稀疏包(sparse package),就能进主菜单。
配套代码:03-win11-packaging。
什么是稀疏包
传统 MSIX 会把你的所有文件打进一个包里安装。稀疏包只打一个清单(AppxManifest.xml),文件仍留在你原来的安装目录——注册时用 -ExternalLocation 指向那个目录即可。这样非打包的 Win32 应用能“低成本”获得包标识,解锁 Win11 主菜单、Share、通知等能力。见官方文档。
三个清单,各司其职
打包扩展有点绕的地方在于:有三处身份信息必须完全对上。
① package/AppxManifest.xml —— 稀疏包清单。两段扩展是关键:
<!-- 声明进程内 COM 服务器:Clsid=第②章的命令,Path=外部目录里的 DLL -->
<com:Extension Category="windows.comServer">
<com:ComServer>
<com:SurrogateServer DisplayName="FileInfo ExplorerCommand">
<com:Class Id="A3F1C2D4-5E6B-4789-9012-3456789ABCDE"
Path="w11menu.dll" ThreadingModel="STA" />
</com:SurrogateServer>
</com:ComServer>
</com:Extension>
<!-- 把该 CLSID 注册成文件资源管理器右键命令(这就是进主菜单的开关) -->
<desktop4:Extension Category="windows.fileExplorerContextMenus">
<desktop4:FileExplorerContextMenus>
<desktop5:ItemType Type="*">
<desktop5:Verb Id="FileInfoCmd" Clsid="A3F1C2D4-5E6B-4789-9012-3456789ABCDE" />
</desktop5:ItemType>
</desktop4:FileExplorerContextMenus>
</desktop4:Extension>还需 <uap10:AllowExternalContent>true</uap10:AllowExternalContent>、runFullTrust + unvirtualizedResources 能力、以及一个 TrustLevel=mediumIL、RuntimeBehavior=win32App 的 Application(DLL 项目没有真 exe,用个幽灵 exe 占位,右键命令不会去启动它)。
② app.manifest —— 嵌入 DLL 的并排清单,用 msix 元素把这个二进制绑到包标识:
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="DavidApp.ShellExtDemos.Win11Menu" type="win32" />
<msix xmlns="urn:schemas-microsoft-com:msix.v1"
publisher="CN=DavidApp Shell Ext Demos"
packageName="DavidApp.ShellExtDemos.Win11Menu"
applicationId="App" />
</assembly>CMake 用 /MANIFEST:EMBED /MANIFESTINPUT 把它嵌进 w11menu.dll。
这是最容易漏、也最坑的一步:DLL 里不嵌这个 msix 标识清单,资源管理器就不会把它当作已打包组件加载——命令死活不出现,且没有任何报错。
③ 证书 —— 签名证书的 Subject 必须等于清单里的 Publisher。
一句话记忆:证书 Subject = AppxManifest 的
Identity/Publisher= app.manifest 的msix/@publisher,三处一字不差。
复用第②章的处理器
dllmain.cpp 只剩最精简的 DllGetClassObject / DllCanUnloadNow,处理器直接编译第②章的 ExplorerCommand.cpp:
add_library(w11menu SHARED
dllmain.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../02-explorer-command/ExplorerCommand.cpp # 复用!
w11menu.def)
set_target_properties(w11menu PROPERTIES
LINK_FLAGS "/MANIFEST:EMBED /MANIFESTINPUT:\"${CMAKE_CURRENT_SOURCE_DIR}/app.manifest\"")打包后不再需要 DllRegisterServer——注册完全由稀疏包完成。
一键构建 + 注册
示例的 build-package.ps1 把六步串起来:
.\build-package.ps1 # 管理员 + Win11 开发者模式cmake构建带嵌入清单的 DLL;- 组装“外部位置”目录(DLL + 占位资源);
makeappx pack /nv打稀疏包;New-SelfSignedCertificate自签;signtool签名,并把公钥证书导入 受信任人(否则报0x800B0109 CERT_E_UNTRUSTEDROOT);Add-AppxPackage -ExternalLocation注册。
成功后右键任意文件,「显示文件信息」就直接出现在 Win11 主菜单里了。
自签名 + 侧载仅用于开发测试。要分发给别人,需用受信任 CA 的证书(或 Azure Trusted Signing);上架微软商店则用完整 MSIX。