# Release 0.4 第2周:修复 Nextcloud 桌面客户端中的 Windows 错误

发布: (2025年12月12日 GMT+8 10:09)
6 min read
原文: Dev.to

Source: Dev.to

转向新的挑战

在为 OpenCTI 提交我的 pull request 后,我想在 Release 0.4 的后半段尝试一些不同的东西。我决定探索 Nextcloud 桌面客户端GitHub),这是一款被全球数百万人使用的流行开源文件同步工具。

Nextcloud 允许用户在设备之间同步文件,同时保持对其数据的控制。桌面客户端是一个使用 C++ 编写的应用程序,深度集成了 Windows、macOS 和 Linux。这对我来说是一次显著的舒适区外的尝试,因为我的大部分经验都是在 JavaScript,而不是 C++。

我发现的 Bug

在浏览 Nextcloud 的 issue 时,我看到了 Issue #9197

https://github.com/nextcloud/desktop/issues/9197

从用户的角度来看,问题很直接:Windows 上的自定义文件夹图标在每次 Nextcloud 同步文件时都会被重置

在 Windows 上,用户可以通过 右键 → 属性 → 自定义 → 更改图标 来设置文件夹的自定义图标。很多人使用此功能来直观地组织文件。但有了这个 bug,每次同步都会擦除这些自定义图标,恢复为默认文件夹图标。

理解根本原因

在修复之前,我需要了解 Windows 如何处理自定义文件夹图标。经过一些研究,我了解到 Windows 使用两样东西:

  • 文件夹内部的隐藏 desktop.ini 文件,其中包含图标路径
  • 文件夹上设置的 FILE_ATTRIBUTE_SYSTEM 标志

这两者必须同时存在,才能显示自定义图标。如果缺少其中任何一个,Windows 将显示默认图标。

随后,我在 Nextcloud 代码库中寻找可能导致该属性丢失的地方。相关代码位于:

src/libsync/vfs/cfapi/cfapiwrapper.cpp

该文件处理 Windows Cloud Files API (CFAPI),Nextcloud 用它来实现虚拟文件支持。我发现,在同步操作期间,代码会将文件属性设置为默认值(FILE_ATTRIBUTE_NORMALFILE_ATTRIBUTE_DIRECTORY),而没有保留已有的属性,如 FILE_ATTRIBUTE_SYSTEM

我的修复

解决方案是先读取当前文件属性,然后在更新时保留任何已有的标志。我在 cfapiwrapper.cpp 中修改了三个函数。

1. updatePlaceholderState()

添加了读取并保留现有属性的代码:

// Preserve existing file attributes (especially FILE_ATTRIBUTE_SYSTEM for custom folder icons)
const auto currentAttributes = GetFileAttributesW(reinterpret_cast(path.utf16()));
if (currentAttributes != INVALID_FILE_ATTRIBUTES) {
    metadata.BasicInfo.FileAttributes = currentAttributes;
}

2. createPlaceholderInfo()

修改为在设置默认值之前检查现有属性:

const auto currentAttributes = GetFileAttributesW(reinterpret_cast(path.utf16()));
if (currentAttributes != INVALID_FILE_ATTRIBUTES) {
    cloudEntry.FsMetadata.BasicInfo.FileAttributes = currentAttributes;
} else {
    cloudEntry.FsMetadata.BasicInfo.FileAttributes = fileInfo.isDir() ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
}

3. 批量占位符创建(同样在 updatePlaceholderState() 中)

对批量占位符创建函数应用了相同的保留逻辑。

我遇到的挑战

  • 在本地构建项目很困难。 Nextcloud Desktop 依赖复杂,包括 Qt 6 和 KDE 库。在 Windows 上搭建构建环境颇具挑战。
  • 理解 CFAPI。 Windows Cloud Files API 对我而言是全新领域,我花时间阅读 Microsoft 文档以掌握其行为。
  • 在庞大的 C++ 代码库中导航。 代码文件数百个,抽象层次复杂,找到合适的修改位置需要耐心和细致的追踪。

当前状态

我已经完成修复,并根据对代码库的分析确认代码更改是正确的。更改已准备好提交 pull request。

已更改文件

  • src/libsync/vfs/cfapi/cfapiwrapper.cpp

Issue 参考

https://github.com/nextcloud/desktop/issues/9197

我的收获

  • 了解 Windows 文件属性的底层工作方式,尤其是 FILE_ATTRIBUTE_SYSTEM
  • 了解 Cloud Files API (CFAPI) 如何与同步引擎集成。
  • 学会在大型陌生的 C++ 代码库中导航和理解。
  • 在修改文件时保留系统状态的重要性。

展望

  • 提交一个干净的 pull request 并附上完整文档。
  • 响应维护者的代码审查反馈。
  • 努力让修复合并。

结论

第 2 周把我推入了 C++ 和 Windows 系统编程的陌生领域。虽然过程充满挑战,但我对桌面同步应用的内部工作原理有了更深入的了解。结合第 1 周对 OpenCTI 的贡献,我觉得自己在开源之路上取得了实质性进展。在最终的博客文章中,我会分享这两项贡献的结果,并回顾整个 Release 0.4 的学习体会。

Back to Blog

相关文章

阅读更多 »

发布 0.4 结果

我做了什么 目标是添加一个设置,以关闭默认的树形视图: !Tree view https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-do...