NanaZip MSIX 打包原理深度解析:Desktop Bridge、文件系统虚拟化与资源管理器右键菜单集成全揭秘
【免费下载链接】NanaZipThe 7-Zip derivative intended for the modern Windows experience项目地址: https://gitcode.com/JRJSheep/NanaZip
NanaZip 是一款基于 7-Zip 内核、面向现代 Windows 体验的开源压缩管理器,它采用 MSIX 包格式分发,通过 Desktop Bridge(完全信任桌面桥接)技术让经典桌面程序获得"现代化部署"的全部好处。本文将用通俗的语言拆解三大核心问题:MSIX 包是怎么打出来的、文件系统虚拟化为什么会影响 AppData 目录、以及资源管理器右键菜单是如何注入的。无论你是普通用户还是想了解打包原理的新手,读完后都能看懂 NanaZip 的现代化架构。
一、什么是 MSIX?为什么 NanaZip 选择它
MSIX(又称 Appx 包)是微软官方的现代应用打包格式,可以把它理解为"压缩文件 + 一份说明书(清单文件)":
- 声明式安装:Windows 读取清单后自动完成注册,包括开始菜单、文件关联、图标、右键菜单等,无需手写注册表;
- 可原子化更新与卸载:升级和回滚由系统统一管理;
- 签名与校验:包内容经过哈希校验,防止安装后被篡改。
NanaZip 的主入口清单是 Package.appxmanifest,打包工程则是 NanaZipPackage.wapproj。清单中的两行关键配置揭示了 NanaZip 的技术路线:
| 配置 | 值 | 含义 |
|---|---|---|
EntryPoint | Windows.FullTrustApplication | 以"完全信任"模式运行桌面程序(即 Desktop Bridge 路线) |
rescap:Capability | runFullTrust | 申请完全信任能力,可读写任意磁盘路径 |
💡 为什么压缩软件必须是"完全信任"?因为 7-Zip 需要读写用户选定的任意目录,而 UWP 沙箱默认只允许访问有限的"允许位置"。
runFullTrust正是为此设计的。
二、打包全流程:从代码到 .appxbundle
NanaZip 的构建入口是根目录的 BuildAllTargets.proj,它串联了四个阶段:
- RefreshVersion(刷新版本号):从 Git 提交时间推算出形如
主.次.天数.0的版本号,并通过 RefreshAppxManifestVersion.cs 自动回写进Package.appxmanifest的Identity/Version属性——这就是为什么 MSIX 版本号永远比"人读的版本号"多出一位; - Restore(还原依赖):按 Debug/Release × x64 还原整个解决方案;
- Build(编译打包):调用
NanaZipPackage.wapproj构建。wapproj 中声明AppxBundlePlatforms为x64|arm64,即同时为 x64 和 ARM64 平台生成切片,最终产出一个.appxbundle智能包,系统会自动挑选匹配的架构安装; - Packaging(产物整理):把
K7Base.dll、NanaZip.Core.dll、NanaZip.Modern.dll、自解压外壳.sfx等二进制连同符号文件按架构归档,方便发布。
清单还启用了两项现代特性:
<uap10:PackageIntegrity> <uap10:Content Enforcement="on" /> </uap10:PackageIntegrity> <uap16:UpdateWhileInUse>defer</uap16:UpdateWhileInUse>前者是包完整性校验(配合安全加固防止包内容被替换),后者允许应用运行中延迟更新——这也是安装命令行里带-DeferRegistrationWhenPackagesAreInUse参数的原因。
三、Desktop Bridge 与文件系统虚拟化:看不见的"透明层"
Desktop Bridge 让经典桌面程序跑在 MSIX 之上,代价是 Windows 会给程序套一层文件系统虚拟化:对包目录的写操作会被静默重定向到用户沙箱,防止桌面程序"污染"受保护位置。
NanaZip 在清单中显式配置了重定向例外(见 Package.appxmanifest 的virtualization:FileSystemWriteVirtualization节点):
| 例外目录 | 说明 |
|---|---|
LocalAppData | 每个用户独立的本地数据目录 |
LocalAppDataLow | 低完整性进程数据目录 |
RoamingAppData | 可在多设备间漫游的数据目录 |
这些配置解释了 ReadMe.md "已知问题"一节的现象:
- 🚫安全模式下无法使用 NanaZip:Desktop Bridge 的虚拟化依赖完整桌面环境,安全模式缺少相应服务;
- ⚠️Windows 10 下 AppData 写入会被重定向:微软商店策略不允许应用彻底关闭虚拟化,只有上述三个目录被排除,其他位置(尤其是 Win11 中
AppData下非 Local/Roaming 的目录)的写操作仍会被重定向到包沙箱; - 官方也明确提醒:不要手动解包 MSIX 当便携版长期用,那是调试用途,右键菜单和文件关联都不生效。
除清单声明的虚拟化外,NanaZip 还自带一层API 重定向库:K7Base/K7BaseRedirector.cpp 在链接期把FileTimeToLocalFileTime等老 API 直接替换为自实现版本(K7_REDIRECT宏),K7User/K7UserRedirector.cpp 负责用户态 API。这个平台抽象层(K7Base/K7User)让压缩内核在不同系统基线上行为一致,细节可阅读 K7Base/ReadMe.md。
四、右键菜单集成全揭秘:一个 DLL 的旅程
在资源管理器中选中文件右键能看到"NanaZip"菜单,靠的是清单里的三个扩展协作完成:
4.1 注册入口:fileExplorerContextMenus
<desktop4:Extension Category="windows.fileExplorerContextMenus"> <desktop4:FileExplorerContextMenus> <desktop4:ItemType Type="*"> <desktop4:Verb Id="0000NanaZipShellExtension" Clsid="469D94E9-6AF4-4395-B396-99B1308F8CE5" /> </desktop4:ItemType> <desktop5:ItemType Type="Directory"> ... </desktop5:ItemType> <desktop10:ItemType Type="Drive"> ... </desktop10:ItemType> </desktop4:FileExplorerContextMenus> </desktop4:Extension>- 三种
ItemType分别对应文件、文件夹、磁盘驱动器,因此选中任意对象都会出现菜单; - ⚠️ Verb 的 Id 故意以
0000数字前缀开头,是为了在 Windows 10 经典右键菜单中靠排序技巧"抢"到靠前位置(源码注释说明了这一 workaround); - 磁盘驱动器的菜单受系统限制,仅 Windows 11 22H2 及以上显示。
4.2 进程外 COM 服务器:comServer扩展
<com:Extension Category="windows.comServer"> <com:ComServer> <com:SurrogateServer DisplayName="NanaZip Shell Extension"> <com:Class Id="469D94E9-..." Path="NanaZip.ShellExtension.dll" ThreadingModel="STA" /> </com:SurrogateServer> </com:ComServer> </com:Extension>关键点:SurrogateServer意味着 COM 类运行在包自己的独立进程中,而不是宿主在 Explorer 进程里加载 DLL。这既避免了插件崩溃拖垮资源管理器,又符合商店"包隔离"规则。
4.3 菜单逻辑:IExplorerCommand 实现
菜单内容真正由 NanaZip.UI.Modern/NanaZip.ShellExtension.cpp 实现。它实现IExplorerCommand接口,按"根命令 + 子命令"两级组织:
- 根命令
ExplorerCommandRoot负责枚举子命令(图标取自主程序-1号图标); - 子命令覆盖:打开、测试压缩包、解压到、解压到当前文件夹、智能解压、添加到 7z/zip 压缩包、邮件压缩、CRC32/CRC64/SHA-1/SHA-256 哈希计算等;
- 解压前会用扩展名黑名单(图片、视频、文本等)判断"是否需要解压",并自动生成
压缩包名\子文件夹,分卷(.part001/.001)也能正确识别; - 菜单文案走多语言资源(
LangString),支持整套界面语言。
五、文件关联与执行别名:老用户无缝迁移
除了右键菜单,清单还声明了两类"存在感"很强的扩展:
- 文件类型关联(
windows.fileTypeAssociation):注册了.7z、.zip、.rar、.zst、.lz4等 60 余种扩展名,双击压缩包即唤起 NanaZip;Assets\ArchiveFile.png提供了压缩包文件图标(见 Assets/PackageAssets/ 目录,包含全部 108~1024px 的图标规格); - 执行别名(
appExecutionAlias):这是迁移神器——
| 别名 | 指向 | 作用 |
|---|---|---|
7z.exe/NanaZipC.exe/K7C.exe | NanaZip.Universal.Console.exe | 命令行工具 |
7zG.exe/NanaZipG.exe | NanaZip.Universal.Windows.exe | 图形模式 7-Zip 兼容 |
7zFM.exe/NanaZip.exe | NanaZip.Modern.FileManager.exe | 新版主界面 |
7zFM.exe和7z.exe带AllowOverride="true",不会抢占其他压缩软件的 7-Zip 别名;而NanaZip.exe是独占的。这样依赖7z.exe的脚本几乎可以零改动迁移。
六、双通道发布与版本管理
NanaZip 在微软商店分Release(稳定)与Preview(预览)两条通道,两者的差异被固化在 Documents/ChannelSwitchNote.md 中:
- 包标识名不同:
40174MouriNaruto.NanaZipvs40174MouriNaruto.NanaZipPreview(清单Identity/Name中的 GUID 前缀是作者的开发者账号前缀); - 右键菜单名称不同:
NanaZipvsNanaZip Preview(即NanaZip.ShellExtension.cpp中GetTitle返回的字符串); - 菜单 Clsid 也不同,避免两版共存时菜单互相干扰。
版本号由构建系统自动计算(BuildAllTargets.proj中"距项目创建日的天数"),保证了商店更新检查能感知每一个构建。
七、安装与验证:一条命令看懂 MSIX 部署
对于拿不到微软商店的机器,NanaZip 提供带 XML 许可证的 MSIX 包,为所有用户部署只需一条管理员命令:
Add-AppxProvisionedPackage -Online -PackagePath .\NanaZip.msix -LicensePath .\NanaZip.xml为当前用户安装则用:
Add-AppxPackage -DeferRegistrationWhenPackagesAreInUse -ForceUpdateFromAnyVersion -Path .\NanaZip.msix⚠️ 注意:离线安装后必须联网启动一次应用,Windows 才能向授权服务器完成许可证激活,否则可能无法启动。
安装后可在"设置 → 应用"中查看,右键菜单若未立即出现,重启一次资源管理器进程即可。
小结
NanaZip 的 MSIX 打包实践是一次教科书式的"经典桌面应用现代化":
- 用
runFullTrust+ Desktop Bridge 换取任意路径读写能力; - 用
FileSystemWriteVirtualization例外列表把配置数据留在真实 AppData; - 用
fileExplorerContextMenus+ 进程外 COM 实现安全、隔离的右键菜单; - 用执行别名平滑接管 7-Zip 生态位;
- 用版本自动化 + 双通道清单维护,支撑商店级发布节奏。
理解了这套机制,你就能看懂绝大多数"现代化改造"的压缩工具是怎么在 Windows 上同时做到既开放、又受控的。
【免费下载链接】NanaZipThe 7-Zip derivative intended for the modern Windows experience项目地址: https://gitcode.com/JRJSheep/NanaZip
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考