更新记录(仅首版,2026年08月20日 发布)
- 首次发布
引用本文(DOI(已登记存档): 10.5281/zenodo.22176357)
以下 DOI 指向先前登记的存档,内容可能与当前正文不同。引用当前正文时,请使用本页网址。
Go Komura(2026)。《OneDrive“按需文件”与业务应用——占位符打破的前提与对策》。小村软件有限公司。 https://comcomponent.com/zh-CN/blog/onedrive-files-on-demand-business-apps/
- DOI(已登记存档)
- 10.5281/zenodo.22176357
- DOI(上次登记版本)
- 10.5281/zenodo.22176358
“业务应用读不了保存在桌面上的 CSV。”“换了电脑之后,一直正常的导入处理以‘找不到文件’停下来。”文件资源管理器里明明看得到文件,于是重新保存、重启应用都试过,原因仍然查不出来。
这时要分开确认的是文件的位置和内容是否在本地。OneDrive 的“已知文件夹移动(KFM)”会改变桌面等位置,“按需文件”则把内容留在云端,直到真正需要时才取回。业务应用如果仍以传统的本地文件为前提,这两项都会带来问题。12
本文面向中小企业的信息系统负责人和 Windows 应用开发者,先给出接到咨询时的排查步骤,然后梳理占位符的机制与属性的读法、业务应用会踩的坑,以及开发端和信息系统部门各自的对策。
1. 先讲结论——把“位置”和“实体”分开确认
文件在文件资源管理器里看得到,既不保证应用引用的路径正确,也不保证内容能马上读到。首先要把下面两件事区分开。
| 发生变化的前提 | OneDrive 的功能 | 对业务应用的影响 | 首先确认什么 |
|---|---|---|---|
| 桌面等位置的实际路径 | KFM(已知文件夹移动) | 使用固定路径的应用找不到移动后的文件 | 应用配置里的路径,以及已知文件夹当前的路径 |
| 文件的内容位于本地 | 按需文件 | 存在性检查能通过,但读取时会等待下载或报错 | 状态图标、文件属性、OneDrive 的运行状态 |
KFM 移动后的路径用已知文件夹 API 获取。按需文件的状态先用属性查看,只打开确实需要内容的文件。在当前的同步应用中,按需文件默认启用,Microsoft 也建议保持启用。并不是一出问题就必须从一开始整体禁用。134
应急处理是把业务需要的文件夹设为“始终保留在此设备上”,先把实体留在本地。但路径错误仍要另行修正。长期对策则是,应用端重新审视保存位置、读取处理和监视处理,信息系统部门用固定和策略维持必要的状态。
图中实线表示始终成立的关系,虚线表示带条件的关系(成立条件写在详情页各关系的说明中)。关系的完整列表(共 16 条,附依据与确信度)以及主要概念的定义,汇总在知识地图详情页(日文)。数据:JSON-LD / Turtle
2. 接到“文件读不了”的咨询时如何排查
2.1. 从路径开始,依次确认 6 项
不要一上来就打开目标文件夹里的全部文件,而是从路径和元数据查起。这套步骤的目的,是把存在性检查和读取分开考虑。
| # | 确认什么 | 方法 | 能得到什么结论 |
|---|---|---|---|
| 1 | 路径是否位于 OneDrive 之下 | 用 echo %OneDrive% 查看同步根目录,与目标路径比对。再用文件资源管理器的地址栏确认“桌面”的实际路径 |
问题是否与 KFM、OneDrive 有关 |
| 2 | 文件的状态 | 用 attrib <路径> 查看 U(仅联机)、P(固定)、O。同时看属性对话框里的“占用空间” |
实体是否在本地,还是只有占位符 |
| 3 | OneDrive 的运行状态 | 任务栏通知区域的图标(已登录、已暂停、错误)、Get-Process OneDrive |
是否处于能够水化的状态。0x8007016A 典型地对应停止运行或配置不当5 |
| 4 | 网络 | 公司代理、带宽、到 OneDrive 服务的连通性 | 下载本身是否可行 |
| 5 | 磁盘可用空间 | 目标卷的剩余空间。空间偏小时,也有让 OneDrive 阻止下载的策略 | 水化失败的另一类原因 |
| 6 | 失败的记录 | 记下应用的错误码和发生时刻,与同步应用显示的错误比对 | 问题出在应用端还是 OneDrive 端 |
个人版和工作版等,可以根据所用的 OneDrive,把 OneDrive / OneDriveCommercial 环境变量也当作线索。不要只凭“桌面”这个显示名就下判断,关键是与应用实际引用的路径比对。
如果既不在 OneDrive 之下,也不是占位符,就不要继续只怀疑 OneDrive,而要转向共享文件夹、路径长度等方面的确认。另一类原因在网络驱动器与 UNC 路径的陷阱和 MAX_PATH 与 Windows 路径、文件名的陷阱中做了梳理。
2.2. 把应急处理和“业务能否恢复”的确认分开
如果因为仅联机而读不到内容,就右键单击目标文件夹并选择“始终保留在此设备上”。用脚本切换时,要像 attrib +p -u <文件夹> /s /d 这样,在加上固定的同时去掉未固定属性。67
这里要确认的不是“操作做过了”,而是需要的文件确实下载完成、能够读取。固定只是表示“打算保留在本地”的属性,并不能解决 OneDrive 停止运行、网络不稳、可用空间不足等问题。先确认同步应用的状态和目标文件的实体,再重新运行导入处理。36
恢复之后,如果原因在固定路径或数据存放位置,就转向第 6 章的应用端对策;如果原因在实体保留或终端配置不一致,就转向第 7 章的信息系统部门对策。靠固定让它跑通一次,和改成不会复发的设计,是两回事。
3. 到底变了什么——KFM 与占位符的机制
3.1. KFM 会改变桌面等位置的实际路径
KFM(Known Folder Move,已知文件夹移动)在 OneDrive 的设置界面上显示为“备份”“备份重要的文件夹”等。启用后,桌面、文档、图片的实体会移动到 OneDrive 之下。下面是路径的例子。实际的文件夹名和同步根目录因环境而异,请不要把这些字符串原样写进代码。1
| 用户看到的位置 | KFM 之前的实际路径 | KFM 之后的实际路径 |
|---|---|---|
| 桌面 | C:\Users\taro\Desktop |
C:\Users\taro\OneDrive\桌面 |
| 文档 | C:\Users\taro\Documents |
C:\Users\taro\OneDrive\文档 |
| 图片 | C:\Users\taro\Pictures |
C:\Users\taro\OneDrive\图片 |
在新电脑的初始设置(OOBE)中登录 Microsoft 账户或工作账户时,系统会建议开启备份,有些配置就这样一直保持启用。在组织里,还可以用 KFMSilentOptIn 策略在用户没有任何操作的情况下批量移动。不能只假设“用户是自己有意识地设置的”。18
麻烦的是,文件资源管理器里的样子几乎没有变化。使用 SHGetKnownFolderPath 或 .NET 的 Environment.GetFolderPath 的应用能取到移动后的路径。而把 C:\Users\%USERNAME%\Desktop 这类固定路径写死在配置文件或代码里的应用,会一直去找移动前的位置。
也就是说,应对 KFM 首先是路径解析的问题。确定移动后的正确路径之后,再确认这个文件的内容是否在本地。
3.2. 按需文件把“看得见”和“有内容”分成两件事
在启用了按需文件的环境中,同步范围内的文件会显示在文件资源管理器里,而内容可以等到需要时再下载。在其他设备或网页上创建的文件,也会以仅联机的占位符形式出现。24
状态可以通过文件资源管理器的图标区分。9
| 图标 | 状态 | 本地实体 |
|---|---|---|
| 云朵图标 | 仅联机 | 无(只有占位符) |
| 白底对勾 | 本地可用 | 有(但之后可能被自动释放) |
| 绿底白对勾 | 始终保留在此设备上(固定) | 有(不在自动释放的范围内) |
重要的是,打开过一次得到的“本地可用”,与固定得到的“始终保留在此设备上”并不相同。前者可能因为用户执行“释放空间”,或者因为存储感知,再次变回仅联机。“上个月能读”不能作为这次内容仍然留在本地的依据。210
stateDiagram-v2
accTitle: 按需文件的三种状态与转换
accDescr: 仅联机的文件打开后变成本地可用,但会因释放空间操作或存储感知再次退回仅联机,只有固定的文件不在自动释放的范围内
s1: 仅联机(云朵图标)
s2: 本地可用
s3: 固定(始终保留在此设备上)
s1 --> s2: 打开(水化)
s2 --> s1: 释放空间
s2 --> s1: 存储感知
s1 --> s3: 始终保留在此设备上
s2 --> s3: 始终保留在此设备上
s3 --> s2: 取消固定
图1:只是下载过一次的文件与固定的文件不同,可能成为自动释放的对象。
3.3. 读取时由 Cloud Files API 取回内容
按需文件实现在 Windows 10 版本 1709 引入的 Cloud Files API 之上。在文件系统一侧工作的是名为 cldflt.sys 的迷你过滤器(服务名 CldFlt,Windows Cloud Files Filter Driver),OneDrive 则是使用这套 API 的同步提供程序之一。116
还没有内容的占位符,是只保存文件名、大小、时间戳等元数据的重解析点。按 Microsoft 的说明,保存文件系统头大约要用 1 KB。应用尝试读取内容时,迷你过滤器会要求同步提供程序传输数据,等必要的数据到达后读取才继续。这种取回称为水化(hydration),释放本地实体、让文件退回占位符则称为脱水(dehydration)。11
sequenceDiagram
accTitle: 打开占位符时的水化过程
accDescr: 应用打开占位符并读取时,cldflt.sys 迷你过滤器检测到请求并指示同步提供程序传输数据,等下载完成后读取才继续
participant app as 业务应用
participant flt as cldflt.sys 迷你过滤器
participant sync as 同步提供程序
app->>flt: 打开并请求读取
flt->>sync: 指示传输数据
sync-->>flt: 下载完成
flt-->>app: 读取继续进行
图2:在看似本地文件的读取过程中,插入了同步提供程序的下载。
出于兼容性,Cloud Files API 会对同步引擎和 %systemroot% 之下的进程以外隐藏“这是重解析点”这件事。因此在普通应用看来,它只是“打开稍慢一点的普通文件”。不要只靠专门处理重解析点的代码来判断,而要确认下一章讲的属性。11 重解析点本身的机制在 NTFS 的内部结构中做了讲解。
在文件资源管理器的属性对话框里,“大小”显示的是文件本来的大小,而“占用空间”几乎是 0。有文件名、能取到大小,与内容在本地,是两回事。
4. 用文件属性查看状态
4.1. 分清内容的状态和保留的意图
占位符的状态以普通文件属性的形式对外公开。主要属性如下。3
| 属性 | 值 | 含义 |
|---|---|---|
| FILE_ATTRIBUTE_OFFLINE | 0x00001000 | 数据不能立即使用(面向分层存储管理的传统属性) |
| FILE_ATTRIBUTE_RECALL_ON_OPEN | 0x00040000 | 本地没有物理实体。只出现在目录枚举的结果中 |
| FILE_ATTRIBUTE_PINNED | 0x00080000 | 用户希望“始终保留在本地”(固定) |
| FILE_ATTRIBUTE_UNPINNED | 0x00100000 | 不必在本地保留实体(打算转为仅联机) |
| FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS | 0x00400000 | 内容的一部分或全部不在本地。读取时会从远端取回 |
OFFLINE 和 RECALL_ON_DATA_ACCESS 是判断数据能否立即使用的线索。而 PINNED / UNPINNED 表示的是是否打算保留在本地的意图。不要只看 P 或 U 就断定下载已经完成。另外,RECALL_ON_OPEN 是出现在目录枚举结果中的属性,并不是所有取属性的 API 都能同样得到。3
4.2. 用 attrib 查看和修改时,注意切换的顺序
用 attrib <路径> 可以查看属性。O 表示脱机,P 表示固定,U 表示未固定。Microsoft 把 OneDrive 的状态与设置命令的对应关系整理如下。76
| 按需文件的状态 | 属性 | 设置命令 |
|---|---|---|
| 始终可用(固定) | Pinned(显示 P) | attrib +p <路径> |
| 本地可用 | 既不是 P 也不是 U | attrib -p <路径> |
| 仅联机 | Unpinned(显示 U) | attrib +u <路径> |
对仅联机(U)的文件只执行 attrib -p,U 仍然保留,内容也不会取回。即使目标是“本地可用”,也需要先用 +p 变成“始终可用”让它下载,然后再改为 -p 这样的顺序。在切换既有状态的脚本里,要像 attrib +p -u 那样把相反的属性也去掉。6
4.3. 用 PowerShell 批量查看 CSV 的状态
只查看文件属性的话,不会引发内容的水化。下面的例子用已知文件夹 API 取得“文档”的路径,并查看 CSV 的属性。
function Test-CloudPlaceholder {
param([Parameter(Mandatory)][string]$Path)
$value = [int](Get-Item -LiteralPath $Path -Force).Attributes
[pscustomobject]@{
Path = $Path
Offline = ($value -band 0x00001000) -ne 0 # FILE_ATTRIBUTE_OFFLINE
RecallOnDataAccess = ($value -band 0x00400000) -ne 0 # 内容并非全部在本地
Pinned = ($value -band 0x00080000) -ne 0 # 始终保留在此设备上
Unpinned = ($value -band 0x00100000) -ne 0 # 仅联机
}
}
# 批量检查“文档”文件夹之下的 CSV(不会下载内容)。
# 路径用已知文件夹 API 解析。如果把“文档”这个显示名写死,
# 在实际文件夹名为英文(Documents)的环境或某些 KFM 配置下会得到不存在的路径
Get-ChildItem ([Environment]::GetFolderPath('MyDocuments')) -Recurse -Filter *.csv |
ForEach-Object { Test-CloudPlaceholder $_.FullName } |
Where-Object RecallOnDataAccess |
Format-Table -AutoSize
之所以强制转换为 [int],是因为 .NET 的 FileAttributes 枚举类型里没有定义 RECALL_ON_DATA_ACCESS 之类的名称。转成数值后用位运算判断。避免写死“文档”这个显示名,以及不读内容只看属性,这两点同样重要。
5. 业务应用中暴露出来的 6 个问题
占位符并不是损坏的文件。但它与“存在的文件就能马上读”“本地的监视事件都来自用户操作”这类前提并不相容。
| 症状 | 实际发生的事 | 需要重新审视的对象 |
|---|---|---|
| 文件存在却打不开 | 读取时的取回失败 | OneDrive、网络、错误处理 |
| 批量处理慢得离谱 | 读过内容的文件被一个接一个地下载 | 全量读取、哈希计算、备份 |
| 只有一部分文件被排除 | 属性的完全相等判断等没有考虑到附加属性 | 判断属性、修改属性的代码 |
| 收到大量监视事件 | 同步、属性更新以及回写到同一位置都会产生通知 | FileSystemWatcher 与输入输出位置 |
| 出现同步错误或重复文件 | 独占锁或多台电脑同时编辑与同步冲突 | 加锁时长、文件存放位置、重复处理 |
| 夜间流量和磁盘占用增加 | 扫描和建立索引会取回内容 | 安全产品、搜索索引器 |
5.1. 存在性检查能通过,读取却失败
即使是仅联机的文件,相当于 File.Exists() 的存在性检查,以及取得属性和大小,也可能成功。真正开始读取内容时才需要水化,因此 OneDrive 停止运行、已退出登录、已暂停以及网络不稳等,都会表现为读取失败。文件较大时,等待下载还可能变成应用的超时。
云文件相关的错误包括与 ERROR_CLOUD_FILE_PROVIDER_NOT_RUNNING 对应的 0x8007016A(“云文件提供程序未运行”)等。不要一律归结为“文件不存在”,请记录原始错误码和目标路径。5
5.2. 批量处理会诱发全量下载
把读取文件夹内全部文件的批处理、哈希计算、全文检索、自制备份指向 OneDrive 之下,被读取内容的文件就会接连发生水化。几 GB 的文件夹,增加的不只是处理时间,还有流量和本地磁盘占用。在容量偏小的电脑上,这会因可用空间不足引发另一类故障。
当应用取回用户并未显式打开的文件时,Windows 可能弹出通知,向用户给出阻止的选项。一旦在那里被阻止,该应用之后的下载都会失败。解除的位置在“设置”的“文件自动下载”。遇到“只有特定的电脑失败”时,也要确认这个状态。11
5.3. 没有考虑附加属性的代码会误判
像 attributes == FileAttributes.Archive 这样用完全相等来判断,会把附带了其他属性的文件当作“意料之外”而排除掉。也有备份、同步工具把 OFFLINE 理解成“已转存到磁带”而跳过,或者反过来把不必要的文件也取回的情况。做只读检查或修改存档位时,不要破坏其他属性的组合,这一点同样必要。
Microsoft 面向迷你过滤器的指南中有一条提醒:不要对带有 RECALL_ON_DATA_ACCESS 的文件轻率地发出读写。面向内核驱动程序的约束与用户模式的实现并不相同,但一旦触碰内容就会产生取回成本这一点,业务应用同样需要注意。12
5.4. FileSystemWatcher 也会捕捉到同步的活动
用 FileSystemWatcher 监视 OneDrive 之下时,除了用户的操作,来自其他设备的变更同步、水化与脱水引起的属性和大小更新,同样可能触发事件。
而且,如果把导入结果回写到同一个文件夹,就会形成写入、上传、属性更新、再次触发事件的循环。
flowchart TB
accTitle: 监视与回写造成的变更通知循环
accDescr: 收到变更事件的监视应用把导入结果回写到同一个文件夹,同步应用的上传和属性更新会再次触发事件,形成变更通知风暴般的循环
ev["变更事件"] --> proc["监视应用执行导入"]
proc --> write["回写到同一个文件夹"]
write --> up["同步应用上传"]
up --> attr["属性和大小被更新"]
attr --> ev
sync["其他设备变更的同步"] -.-> ev
图3:把导入结果回写到被监视的位置,会把同步应用的活动也卷进来,通知可能反复出现。
需要对事件做稀释和确认实体的原因,在 FileSystemWatcher 实务指南中做了说明。在 OneDrive 之下,不把通知直接理解成“又到了一个可导入的文件”的设计就更加重要。
5.5. 独占锁与多台电脑的编辑会与同步冲突
业务应用以独占锁打开文件期间,同步应用无法上传或更新这个文件。像 Access 的 .accdb、自有格式的数据文件、日志那样长时间打开的设计,一旦放在 OneDrive 之下,同步错误就会变成常态。
多台电脑编辑同一个文件时,为了保留两边的版本,还可能生成带电脑名的文件或“……的副本”这类冲突副本。以“一个文件夹一个文件”为前提的导入处理,会因为这种重复而出错。加锁的设计请另见文件对接互斥控制基础知识。
5.6. 扫描和搜索索引器也会取回内容
读取内容的并不只有业务应用。杀毒软件的全盘扫描和搜索索引器,只要访问占位符的内容,同样会诱发水化。
Azure File Sync 的规划指南说明,Microsoft Defender 等在按需扫描时会跳过带有 RECALL_ON_DATA_ACCESS 属性的文件。不过这是产品一侧的适配,并非所有安全产品都会做同样的考虑。遇到“每次夜间扫描,网络和磁盘都被占满”“设成仅联机的文件第二天早上全都变回了本地实体”时,也要调查扫描一侧的行为。13
6. 应用开发端的对策——不轻易打开,并把保存位置分开
6.1. 枚举时先看属性,只读确实需要内容的文件
基本方针是把占位符当作“取回有成本的文件”来对待。日志收集、哈希计算、预览生成等并非必需的处理,要留出跳过的选项。
下面是先确认属性再导入 CSV 的例子。
// .NET 的 FileAttributes 中未定义的值,用数值来定义
const FileAttributes RecallOnDataAccess = (FileAttributes)0x00400000;
const FileAttributes RecallOnOpen = (FileAttributes)0x00040000;
static bool IsCloudPlaceholder(FileAttributes attributes) =>
(attributes & (RecallOnDataAccess | RecallOnOpen | FileAttributes.Offline)) != 0;
foreach (var file in new DirectoryInfo(watchFolder).EnumerateFiles("*.csv"))
{
if (IsCloudPlaceholder(file.Attributes))
{
log.Warn($"{file.Name} 是仅联机文件,本次跳过处理");
continue;
}
Import(file.FullName);
}
这个例子的方针是本次不处理可能为仅联机的文件。但业务上必须导入的文件,不能只留一条警告日志就当作已经处理完。要把事先保证实体的做法,和读取失败时的处理方式一并定下来。
6.2. 不要把 FILE_FLAG_OPEN_NO_RECALL 当成“不会通信”的保证
CreateFile 的 FILE_FLAG_OPEN_NO_RECALL 表示的意图是:把请求的数据继续留在远端,不搬回本地存储。它并不是禁止为读取内容而进行数据传输的标志。14
想避开带宽和等待时间的排查,只用属性、大小、时间戳等元数据就够了。可以使用枚举结果中的信息,必要时以访问权限 0 打开来取得属性,总之选择不请求读取访问的方法。14
6.3. 把数据存放位置和失败时的提示写进规格
在 KFM 环境里,“文档”也可能落在 OneDrive 之下。应用的配置、数据库、工作文件要放在 %ProgramData%、%LocalAppData% 等与用途相符的位置,不要轻易把桌面或文档选作默认的保存位置和导入位置。具体的判断在 Windows 应用的数据保存位置怎么选中做了汇总。
即使允许用户自选保存位置,也要事先决定选到 OneDrive 之下时的行为。把依据 OneDrive / OneDriveCommercial 环境变量得知的同步根目录当作线索给出警告、拒绝在那里存放锁文件和数据库,这类判断都要写进规格。
读取失败时,除了目标路径和错误码,如果能判断出它位于 OneDrive 之下,也要把这条信息一并显示并记录。哪怕只是在检测到 0x8007016A 等错误时提示一句“请确认 OneDrive 的状态”,现场和服务台也更容易按同一套步骤去查。
7. 信息系统部门的对策——用固定和策略维持状态
7.1. 只固定必要的文件夹
在整体禁用按需文件之前,先把业务应用要读的文件夹设为“始终保留在此设备上”。装机时使用 attrib +p -u <文件夹> /s /d 的情况下,也要确认下载完成后再交付给业务使用。64
只是“事先打开过一次”,挡不住之后的自动释放。要点是按文件夹为单位固定必要的位置,并把这个状态也写进支持流程。
7.2. 有意识地配置 KFM 和按需文件
为避免“回过神来已经启用了”,用组策略或 Intune 统一管控这些配置。还有禁止用户撤销的策略,因此不能只看终端上的界面,也要确认组织正在应用的配置。81
| 目的 | 策略(注册表值) | 效果 |
|---|---|---|
| 管控按需文件 | Use OneDrive Files On-Demand(FilesOnDemandEnabled) | 启用后新用户默认为仅联机。禁用则回到传统的全量同步 |
| 批量套用 KFM | Silently move Windows known folders to OneDrive(KFMSilentOptIn) | 无需用户操作即可移动桌面等文件夹 |
| 禁止 KFM | Prevent users from moving their Windows known folders to OneDrive(KFMBlockOptIn) | 禁止移动已知文件夹 |
| 禁止撤销 KFM | Prevent users from redirecting their Windows known folders to their PC(KFMBlockOptOut) | 禁止用户自行撤销 |
| 缩减团队网站占用的容量 | Convert synced team site files to online-only(DehydrateSyncedTeamSites) | 把已同步的团队网站转为仅联机(注意它的作用方向是让本地实体消失) |
DehydrateSyncedTeamSites 是一项作用方向为减少已同步团队网站本地实体的策略。需要的文件变回云朵图标时,除了用户的“释放空间”操作,也要确认这类组织层面的配置。8
7.3. 确认存储感知和全量同步的成本
存储感知(Storage Sense)具备把一定天数未打开的云文件退回仅联机的功能。天数可以用 ConfigStorageSenseCloudContentDehydrationThreshold 配置,该策略的默认值 0 表示不自动退回。不过,用户可能已经在设置界面里启用了它,组织也可能为小容量终端做过配置。10
受影响的是没有被显式固定的“本地可用”文件。已固定的文件不在自动释放的范围内,因此遇到“上周还能打开,却变回了云朵图标”时,要确认它是否真的带有 P 属性。4
禁用 FilesOnDemandEnabled 会回到传统的全量下载同步,但磁盘占用和首次同步的带宽负载都会增加。Microsoft 建议保持启用。请把禁用当作确认了目标用户的数据量和磁盘容量之后才采取的、范围有限的措施。84
在咨询受理模板里,嵌入第 2 章的“路径 → 属性 → OneDrive 运行状态 → 网络 → 可用空间 → 记录”。这样即使负责人换了,也不会胡乱切换配置,而能按同样的顺序查找原因。
8. 小结
OneDrive 环境下的文件故障,先把“位置是不是变了”和“内容是不是需要取回”分开,思路就清楚了。KFM 用已知文件夹 API 做路径解析来应对,按需文件用“先确认属性、只读必要内容”的设计来应对。
在此基础上,重新审视回写到被监视位置、长时间独占锁、全量扫描这类处理会与同步如何叠加。应用的内部数据从 OneDrive 之下分离出来,业务上必需的文件则用固定和策略维持本地实体。这样的分工,是不让事情停留在应急处理的基础。
下次接到“文件明明在,却读不了”的咨询时,请先回头问一句。
应用看的是现在正确的位置吗?还有,那个文件的内容,真的在本地吗?
相关文章
- Windows I/O 的深层(第 5 回)——NTFS 的内部结构:从 MFT 理解文件系统
- FileSystemWatcher 实务指南 - 应对遗漏与重复
- 网络驱动器与 UNC 路径的陷阱——业务应用中处理文件服务器(共享文件夹)的实务
- 文件对接互斥控制基础知识 - 文件锁与原子 claim 的最佳实践
- Windows 应用的数据保存位置怎么选——SQLite / JSON / 注册表 / Access 判断表
- MAX_PATH 与 Windows 路径、文件名的陷阱——260 字符限制、保留名称、末尾句点、大小写
相关咨询领域
合同会社小村软件承接“一直正常的导入处理在换电脑之后不能用了”“只有特定的电脑读不了文件”这类与 OneDrive、云存储相关的业务应用缺陷调查,以占位符为前提的文件处理与监视处理的设计和改造,以及 KFM、按需文件环境下保存位置设计的评审。从现象排查开始也可以,欢迎随时咨询。
参考链接
-
Microsoft Learn,Redirect and move Windows known folders to OneDrive。介绍 KFM 会把桌面、文档、图片移动到 OneDrive 之下,以及提示、静默套用、禁止撤销、禁止移动等各项策略。 ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft 支持,Save disk space with OneDrive Files On-Demand for Windows。介绍按需文件的三种状态,以及“始终保留在此设备上”“释放空间”这两项操作。 ↩ ↩2 ↩3
-
Microsoft Learn,File Attribute Constants。介绍 FILE_ATTRIBUTE_OFFLINE、RECALL_ON_OPEN、RECALL_ON_DATA_ACCESS、PINNED、UNPINNED 各属性的定义和取值。 ↩ ↩2 ↩3 ↩4
-
Microsoft Learn,Recommended sync app configuration。介绍按需文件默认启用且建议保持启用,以及存储感知会清理“未固定的本地可用文件”。 ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn,Error 0x8007016a when copying files in OneDrive。介绍错误 0x8007016A“The cloud file provider is not running”会在 OneDrive 配置不当或停止运行时发生,以及解决步骤。 ↩ ↩2
-
Microsoft Learn,Query and set Files On-Demand states in Windows。介绍用 attrib 查看按需文件状态、用 +p、-p、+u 进行设置,以及 CldFlt 服务。 ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn,attrib。介绍 attrib 命令的语法,以及包含 O(脱机)、P(固定)、U(未固定)在内的属性标志。 ↩ ↩2
-
Microsoft Learn,IT Admins - Use OneDrive policies to control sync settings。介绍 FilesOnDemandEnabled、KFMSilentOptIn、KFMBlockOptIn、KFMBlockOptOut、DehydrateSyncedTeamSites 等用 GPO/Intune 配置 OneDrive 同步应用的各项策略。 ↩ ↩2 ↩3 ↩4
-
Microsoft 支持,What do the OneDrive icons mean?。介绍文件资源管理器中显示的云朵、对勾等状态图标的含义。 ↩
-
Microsoft Learn,Policy CSP - Storage。介绍存储感知可以把一定天数未打开的云文件转为仅联机,以及默认值 0(不自动退回)和 0~365 天的配置。 ↩ ↩2
-
Microsoft Learn,Build a Cloud Sync Engine that Supports Placeholder Files。介绍云文件 API 的概要、占位符只持有约 1 KB 元数据且打开时会自动水化、重解析点会对同步引擎和 %systemroot% 之下以外的进程隐藏,以及针对后台水化的弹出通知与阻止。 ↩ ↩2 ↩3 ↩4
-
Microsoft Learn,Handling placeholders。介绍占位符应设置 FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS,以及对带有该属性的文件轻率读写会招致不必要的水化和数据损坏。 ↩
-
Microsoft Learn,Plan for an Azure File Sync deployment。介绍杀毒扫描可能引发带 RECALL_ON_DATA_ACCESS 属性的文件被召回,以及 Microsoft Defender 等在按需扫描时会跳过带该属性的文件。 ↩
-
Microsoft Learn,CreateFileW function (fileapi.h)。介绍 FILE_FLAG_OPEN_NO_RECALL 表示“不应把请求的数据搬回本地存储,而应继续留在远端”(并不阻止取得数据本身),以及以访问权限 0 打开来取得属性。 ↩ ↩2
相关文章
共享相同标签的最新文章。可以围绕相近的主题进一步加深理解。
卷影复制服务(VSS)的原理与实务——使用中的文件为什么还能备份
使用中的文件会因共享冲突而无法复制,备份软件为什么却能备份。本文讲解卷影复制服务(VSS)中请求程序、编写器、提供程序的分工,写时复制的原理,vssadmin 的实务操作以及差异区域的陷阱。
睡眠恢复后就出故障的应用——电源事件机制与扛得住恢复的业务应用设计
打开笔记本电脑时业务应用的通信已经断开——原因是设计没有考虑睡眠。本文依据一手资料讲解 WM_POWERBROADCAST 的通知流程、Modern Standby 的行为、断开与重连的设计、睡眠抑制以及调查命令。
多线程实战最佳实践 C 语言篇——以 Win32 API 的方式安全编写
C 语言 × Win32 的多线程自有定式:用 _beginthreadex 创建线程、SRW 锁与条件变量、Interlocked,以及停止事件 + WaitForMultipleObjects 的停止设计。本文还梳理 TerminateThread 的危险与 DllMa...
多线程实战最佳实践 C++ 篇——用 RAII 和 jthread 从结构上杜绝问题
C++ 的多线程里数据竞争就是未定义行为。本文梳理 std::thread 析构函数的陷阱、jthread 与 stop_token 的停止设计、scoped_lock 的死锁规避、atomic 的正确定位,直到与 Win32 同步 API 的区分使用。
多线程实战最佳实践 .NET 篇——增加线程之前必须先定好的事
面向 .NET/C# 梳理防止“线程一开就偶尔崩溃、偶尔卡死”的设计做法,涵盖不自己创建线程而依托 Task、减少共享可变状态、加锁的纪律、用 CancellationToken 设计停止流程,直到 UI 线程的处理方式。
相关主题
与本文相近的主题页面。以本文为起点,可以进一步了解相关服务和其他文章。
Windows 技术主题
汇整 KomuraSoft LLC 关于 Windows 开发、故障调查与既有资产活用文章的主题中心。
常见问题
汇总了咨询这一主题时常见的问题。
- 业务应用说“找不到文件”,读不了放在桌面上的 CSV。这是为什么?
- 多数情况下,原因是桌面文件夹本身已被 OneDrive 的“已知文件夹移动(KFM)”挪到了 C:\Users\<用户名>\OneDrive\桌面 之下,或者文件已经变成仅联机的占位符。应用如果以 C:\Users\<用户名>\Desktop 这类固定路径为前提,就找不到移动后的文件。即使路径正确,仅联机的文件在 OneDrive 停止运行或网络不稳时也可能打不开。请先确认目标路径是否位于 OneDrive 之下,再用 attrib 命令查看是否带有 U(仅联机)。应急处理可以用右键菜单中的“始终保留在此设备上”,把实体留在本地。
- 程序能判断文件是不是仅联机吗?
- 可以。仅联机的占位符会带有 FILE_ATTRIBUTE_OFFLINE、FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS(0x00400000)等属性,因此查看文件属性就能在不下载内容的情况下判断状态。仅取得属性或枚举文件夹不会引发水化(下载)。.NET 的 FileAttributes 中有些值没有定义,需要转换成整数后用位运算判断。如果确实想打开但不读内容,也有 CreateFile 的 FILE_FLAG_OPEN_NO_RECALL 这类手段。
- 禁用按需文件就能解决问题吗?
- 请把禁用当作最后手段。禁用之后,同步范围内的全部文件都会下载到本地,磁盘容量和首次同步的网络负载都会变大,Microsoft 也建议保持启用。实务中更灵活的做法,是只把业务应用要读的文件夹设为“始终保留在此设备上”(固定)。更根本的做法,则是把应用的数据文件夹和导入文件夹改成不放在 OneDrive 管理之下的设计。
- 已经设成“始终保留在此设备上”,却仍有文件不知不觉变回了云朵图标。这是为什么?
- 请先用 attrib 命令确认这个文件是否真的带有固定(P 属性)。已固定的文件不在存储感知自动转为仅联机的范围内,但只是打开过、并未固定的“本地可用”文件,可能因存储感知的配置或策略在一段时间后退回仅联机。此外,用户自己执行“释放空间”,或者把团队网站转为仅联机的策略(DehydrateSyncedTeamSites),也会让云朵图标回来。业务上必须留在本地的文件夹,请按文件夹为单位固定后再投入使用。