第 ③ 章 · 进入 Windows 11 主右键菜单(MSIX / 稀疏包)

不改一行处理器代码,用稀疏包(sparse package)给第②章的 IExplorerCommand 赋予“包标识”,把命令送进 Win11 的新版主右键菜单;含 AppxManifest、嵌入标识清单、自签名与注册的完整流程。

作者 David更新于

前两章的命令,在 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:

CMakeLists.txt(节选)
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 开发者模式
  1. cmake 构建带嵌入清单的 DLL;
  2. 组装“外部位置”目录(DLL + 占位资源);
  3. makeappx pack /nv 打稀疏包;
  4. New-SelfSignedCertificate 自签;
  5. signtool 签名,并把公钥证书导入 受信任人(否则报 0x800B0109 CERT_E_UNTRUSTEDROOT);
  6. Add-AppxPackage -ExternalLocation 注册。

成功后右键任意文件,「显示文件信息」就直接出现在 Win11 主菜单里了。

自签名 + 侧载仅用于开发测试。要分发给别人,需用受信任 CA 的证书(或 Azure Trusted Signing);上架微软商店则用完整 MSIX。

参考

本页目录