Windows 桌面文件夹删除提示权限错误:从 Process Monitor 定位回收站移动失败

本文记录一次 Windows 11 桌面文件夹删除异常的排查过程,重点说明如何把资源管理器的权限提示转换为文件系统事件,并区分已确认的失败阶段与仍需验证的安全软件原因。

1. 问题描述

在桌面删除某个工作目录时,资源管理器先显示“你需要提供管理员权限才能删除此文件夹”。点击“继续”后,界面又显示“你需要来自当前用户的权限才能对此文件夹进行更改”。

脱敏后的“需要提供管理员权限”提示

图 1 资源管理器提示需要提供管理员权限。截图中的设备用户信息和目标文件夹名称已替换为中性标识,错误类型和界面状态保持不变。

脱敏后的“需要来自当前用户权限”提示

图 2 点击“继续”后,资源管理器提示需要来自当前用户的权限。该提示是故障表象,不能单独证明源目录 ACL 异常。

仅凭这两个提示,尚不能判断拒绝发生在源目录、目录中的子项,还是删除流程的后续目标路径。

2. 运行环境

本次检查使用以下环境和对象:

  • 操作系统:Windows 11;
  • 用户:已脱敏为当前交互式用户;
  • 工具:Process Monitor 3.89;
  • 目标目录:C:\Users\<user>\Desktop\g1su2qanegld0;

3. 初步排查与问题推断

3.1 先建立可验证的对照

排查首先记录同一目录在三种操作下的结果:

操作 现场结果 对排查方向的作用
直接使用普通 Delete 出现权限提示,删除未完成 需要捕获资源管理器实际发出的失败请求
先删除内容,再删除空目录 可以删除 说明递归处理和空目录处理的时序可能影响结果
使用 Shift+Delete 可以删除 说明绕过回收站的路径需要单独对照

这个对照把问题拆成两个可能不同的阶段:

  1. 对源文件和源目录发出删除请求;
  2. 将项目移动到 $Recycle.Bin 的回收站请求。

如果源目录 ACL 有问题,绕过回收站的 Shift+Delete 通常也应受到影响。因此下一步先检查源目录,再捕获删除请求,而不是直接修改所有权。

3.2 检查源目录、子项和路径属性

使用 PowerShell 读取目标目录及其内容的所有者、ACL、重解析点和路径长度:

$target = 'C:\Users\<user>\Desktop\g1su2qanegld0'

Get-Item -LiteralPath $target -Force |
    Select-Object FullName,Attributes,LinkType,Target

Get-Acl -LiteralPath $target |
    Select-Object Owner,AccessToString,AreAccessRulesProtected

$items = @(Get-Item -LiteralPath $target -Force) +
         @(Get-ChildItem -LiteralPath $target -Force -Recurse)

$aclSummary = foreach ($item in $items) {
    $acl = Get-Acl -LiteralPath $item.FullName
    [pscustomobject]@{
        Path       = $item.FullName
        Owner      = $acl.Owner
        HasDeny    = [bool]($acl.Access |
            Where-Object { $_.AccessControlType -eq 'Deny' })
    }
}

$aclSummary |
    Group-Object Owner,HasDeny |
    Select-Object Count,Name

[pscustomobject]@{
    ItemCount    = $items.Count
    ReparseCount = @($items | Where-Object {
        ($_.Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0
    }).Count
    MaxPath      = ($items.FullName | ForEach-Object Length | Measure-Object -Maximum).Maximum
}

现场结果是:当前用户拥有目标目录和内部对象,访问列表中有 FullControl,未发现显式拒绝规则;没有发现重解析点,最长路径也不接近 Windows 常见路径限制。 由此可以排除“源目录整体 ACL 缺少删除权限”和“路径过长”这两个方向,但还不能排除文件被占用或过滤器拒绝。

3.3 检查是否有程序直接从目标目录运行

为了区分“目录中有运行程序”和“外部程序访问目录”,检查进程可执行路径是否位于目标目录:

Get-CimInstance Win32_Process |
    Where-Object { $_.ExecutablePath -like "$target\*" } |
    Select-Object ProcessId,Name,ExecutablePath

没有发现从该目录启动的进程。 这个结果不能证明没有任何进程打开目录句柄,因此后续仍需要用 Process Monitor 查看 SHARING VIOLATION 和访问共享模式。

4. 验证与定位

4.1 配置 Process Monitor 并保存完整事件

采集时使用以下流程:

  1. 在 Process Monitor 中按 Ctrl+L 添加 Path begins with <target> Include 过滤器;
  2. 按 Ctrl+X 清空旧记录;
  3. 按 Ctrl+E 开始捕获;
  4. 在资源管理器中直接删除目标目录,直到出现权限提示;
  5. 按 Ctrl+E 停止捕获;
  6. 通过 File → Save 保存当前显示事件为 CSV。

Process Monitor 能记录文件系统请求、结果和请求细节,适合把资源管理器的权限提示转换为可定位的文件系统事件。[1]

导出后可以按附录 A.2 的脚本筛选目标路径、删除操作和失败结果,避免把完整 CSV 直接贴入文章或工单。

这个步骤的检查目的,是把“资源管理器显示的权限提示”转换为可以定位的文件系统结果。SetDispositionInformationFile 用来观察删除标记,SetRenameInformationFile 用来观察移动或重命名,SHARING VIOLATION 用来判断是否有句柄不允许删除共享。

4.2 子项删除请求可以成功

针对目录 g1su2qanegld0 的复现中,Process Monitor 将这些文件系统请求记录在 DllHost.exe 名下,例如:

Operation : SetDispositionInformationFile
Result    : SUCCESS
Detail    : Delete: True

该模式出现在技能目录、工作区文件以及 .codewhale\state\subagents.v1.lock 等对象上。这说明系统接受了对子项的删除标记请求。

这里的 DllHost.exe 是事件中的请求发起进程,不等于实际作出访问控制决定的组件。文件系统过滤器可以在该请求经过内核 I/O 路径时返回拒绝结果,二者需要分开判断。

部分文件还出现了紧接着的 Delete: False 请求。本文不把这一中间事件当作最终结果,判断删除是否失败以之后的目录处理和回收站重命名结果为准。

目录对象在子项尚未全部处理完时出现:

Operation : SetDispositionInformationFile
Result    : NOT EMPTY
Detail    : Delete: True

这是递归删除过程中的正常中间状态,不能单独解释最终的权限弹窗。 目录必须在子项处理完成后才有可能被删除或移动。

4.3 失败发生在移动到回收站

对顶层目录的最后一个关键事件是:

Process Name : DllHost.exe
Operation    : SetRenameInformationFile
Path         : C:\Users\<user>\Desktop\g1su2qanegld0
Result       : ACCESS DENIED
Detail       : ReplaceIfExists: False, FileName: C:\$Recycle.Bin\S-1-5-21-...\$RNNIIVY

SetRenameInformationFile 表示文件系统正在处理重命名请求。目标名称位于当前用户的 $Recycle.Bin SID 目录中,说明失败点不是“删除源目录中的某个文件”,而是把顶层目录移动到回收站时被拒绝。

关键结果:顶层目录移动到回收站的 SetRenameInformationFile 请求返回 ACCESS DENIED。

这一事件与 3.1 节的对照结果一致,说明失败位于回收站移动阶段;Shift+Delete 的机制差异在 5.3 节进一步解释。

4.4 排除回收站目录的基本 ACL 异常

使用当前用户 SID 拼接回收站路径,完整命令见附录 A.4。PowerShell 中 $Recycle.Bin 含有 $,不能直接在双引号字符串中书写,否则 $Recycle 会被当成变量展开。

现场读取结果为:

Owner: H3C\<user>
H3C\<user>: FullControl
BUILTIN\Administrators: FullControl
NT AUTHORITY\SYSTEM: FullControl

回收站目录存在,当前用户拥有完全控制权限,未发现需要通过夺取所有权才能解释的 ACL 缺陷。 因此,“移动到回收站失败”不等于“回收站目录的普通 ACL 错误”,还需要检查文件系统过滤器和安全软件策略。

4.5 检查文件系统过滤器和安全软件

先按附录 A.3 的命令列出服务和系统驱动中与 DLP 相关的项目。

服务和驱动检查列出了 TrellixDLPAgentService 以及以下 DLP 过滤驱动;进程检查另外发现了 fcag.exe:

TrellixDLPAgentService
hdlpflt.sys
hdlpctrl.sys

组件信息显示:

hdlpflt.sys : Trellix Data Loss Prevention - Endpoint 12.11.11.2
fcag.exe    : Trellix Data Loss Prevention - Endpoint 11.11.2.117

同一时间段内,Process Monitor 还记录了 fcag.exe 对该工作目录及其状态文件的访问。可以用附录 A.3 中的 Sysinternals Handle 命令做补充检查。

本次事件中没有出现 SHARING VIOLATION,相关打开请求允许 ShareMode: Read, Write, Delete。 因此证据不支持“普通文件锁直接阻止删除”的解释。DLP 组件与失败事件的时间、目标路径和文件访问关系更匹配。

综合这些结果,可以支持以下判断:

  1. 源目录可以被当前用户打开并请求删除;
  2. 子项删除标记请求可以成功;
  3. 回收站目录的基本 ACL 正常;
  4. 失败请求是移动源目录到回收站时的 SetRenameInformationFile → ACCESS DENIED;
  5. 设备存在正在参与文件访问的 Trellix DLP 用户态组件和文件系统驱动。

因此,本次故障已经定位到“移动到回收站的重命名阶段”。 结合设备上运行的 Trellix DLP 用户态组件和文件系统过滤驱动,DLP 策略或过滤器是当前最可信的原因候选,但现有日志没有包含该事件的内核调用栈,不能仅凭文本断言具体是 hdlpflt.sys 的哪条策略分支返回了拒绝。最终确认仍需要调用栈或 DLP 策略放行测试。

5. 原因分析

5.1 为什么资源管理器会显示“需要自己的权限”

资源管理器收到的是目标重命名操作的访问拒绝结果。错误对话框显示的主体通常是当前用户,但它没有把“源路径访问”和“回收站目标路径访问”区分出来。因此,界面文字容易让人误以为源目录 ACL 缺少当前用户权限。

5.2 为什么清空文件夹后能够删除

文件夹内容被逐个处理后,后续操作的对象和时序发生变化。对于本案例,递归删除阶段能够成功处理内部文件;当目录为空或不再需要执行同样的回收站重命名流程时,资源管理器可能走到不同的操作路径,或者 DLP 策略不再对相同对象组合触发。这个现象本身不能证明源目录权限发生了变化。

5.3 为什么 Shift+Delete 能够成功

Shift+Delete 避开了移动到 $Recycle.Bin 的步骤。它仍然需要对源文件和目录发出删除请求,但不需要把顶层目录重命名到回收站目标路径。因此,它能够绕过本次被拒绝的请求,成为区分“源目录删除权限”和“回收站移动阶段”的有效对照。

6. 修复建议与验证方案

本次排查没有修改源目录 ACL,也没有重置回收站;Shift+Delete 仅作为现场验证手段,确认绕过回收站后可以删除。因此本节记录的是面向管理员的修复建议和复测方法,不把预期结果写成已经完成的修复。

由于设备运行的是企业级 DLP,直接停用服务或删除过滤器不是适合在终端上自行执行的修复方式。

建议由设备管理员或 Trellix 管理员按以下顺序处理:

  1. 在 Trellix DLP 控制台检查针对桌面目录、开发工作区、文件删除和回收站移动的策略;
  2. 以测试目录进行策略排除或临时放行,验证普通 Delete 是否恢复;
  3. 检查 DLP Endpoint 与过滤驱动的版本和策略下发状态,必要时升级到组织批准的修复版本;
  4. 使用 Process Monitor 重新捕获 SetRenameInformationFile 事件的 Stack,确认调用栈是否包含 hdlpflt.sys;
  5. 修复后分别验证普通 Delete、清空后删除和 Shift+Delete,确保结果回到最初的用户场景。

复测时可以使用下面的 Process Monitor 过滤条件:

Path begins with C:\Users\<user>\Desktop\g1su2qanegld0   Include

重点检查以下事件:

SetDispositionInformationFile
SetRenameInformationFile
Result = ACCESS DENIED
Result = SHARING VIOLATION

预期的修复验证结果是:普通 Delete 不再在指向 $Recycle.Bin 的 SetRenameInformationFile 请求上返回 ACCESS DENIED。如果仍然失败,应保留该事件的 Stack、时间、PID 和目标回收站路径,交给 DLP 管理员或厂商继续分析。

7. 总结

这次故障不是源文件夹所有者或普通 NTFS ACL 导致的权限不足。Process Monitor 证明,内部文件的删除请求可以成功,失败发生在顶层文件夹移动到当前用户回收站的 SetRenameInformationFile 操作上。

排查这类问题时,不能只根据资源管理器的权限提示修改所有权或重置 ACL。应先对照普通 Delete 与 Shift+Delete 的行为,再用 Process Monitor 区分:

  • 源文件或目录的删除请求;
  • 目录递归删除过程中的 NOT EMPTY 中间状态;
  • 移动到回收站的重命名请求;
  • 安全软件或文件系统过滤器返回的拒绝结果。

本案例中,回收站基本 ACL 正常,而设备上运行的 Trellix DLP Endpoint 同时参与了相关文件访问。因而最合理的后续方向是检查 DLP 策略、过滤驱动和版本兼容性,并通过调用栈或策略放行测试完成最终归因,而不是继续修改源目录权限。

附录 A:复用检查命令

下面的命令用于启动 Process Monitor 采集、读取目标目录和回收站目录的基本状态。路径中的 $Recycle.Bin 使用单引号或拼接方式,避免 PowerShell 将 $Recycle 误解释为变量。

A.1 启动带日志文件的 Process Monitor

启动前关闭已有的 Process Monitor 实例,避免新参数被已有实例接管:

$procmon = 'D:\5_Tools\SysinternalsSuite\Procmon64.exe'
$work = 'C:\Users\<user>\Documents\procmon-diag'
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
$pml = Join-Path $work "delete-$stamp.pml"

New-Item -ItemType Directory -Path $work -Force | Out-Null
Start-Process -FilePath $procmon -ArgumentList @(
    '/AcceptEula',
    '/BackingFile',
    $pml
)

[pscustomobject]@{
    Pml = $pml
    StartedAt = Get-Date
}

启动后仍需在 Process Monitor 界面中设置 Path begins with <target> Include 过滤器,并按正文 4.1 节的顺序清空、捕获、复现和保存 CSV。/BackingFile 只负责保存原始 PML,不代替界面中的路径过滤。

A.2 筛选导出的 CSV

如果事件较多,可以使用以下命令提取关键操作:

$target = 'C:\Users\<user>\Desktop\g1su2qanegld0'
$csv = 'C:\path\to\captured-events.csv'
$report = 'C:\path\to\delete-relevant.csv'

$events = Import-Csv -LiteralPath $csv | Where-Object {
    $_.Path -like "$target*" -and (
        $_.Operation -match 'Disposition|SetInformation|CreateFile|Cleanup|Close' -or
        $_.Result -match 'ACCESS DENIED|SHARING VIOLATION|LOCK NOT_GRANTED'
    )
}

$selected = $events |
    Select-Object 'Time of Day','Process Name','PID','Operation','Path','Result','Detail'

$selected | Export-Csv -LiteralPath $report -NoTypeInformation -Encoding UTF8
$selected | Format-List

A.3 检查占用句柄和 DLP 组件

$target = 'C:\Users\<user>\Desktop\g1su2qanegld0'
$handle = 'D:\5_Tools\SysinternalsSuite\handle64.exe'

& $handle -accepteula -nobanner $target

Get-CimInstance Win32_Service |
    Where-Object {
        $_.Name -match 'DLP|McAfee|Trellix' -or
        $_.DisplayName -match 'DLP|McAfee|Trellix'
    } |
    Select-Object Name,DisplayName,State,StartMode,PathName

Get-CimInstance Win32_SystemDriver |
    Where-Object {
        $_.PathName -match 'McAfee|Trellix|DLP|hdlp'
    } |
    Select-Object Name,DisplayName,State,StartMode,PathName

A.4 检查源目录和回收站 ACL

$target = 'C:\Users\<user>\Desktop\g1su2qanegld0'
$sid = [System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value
$recycleUser = 'C:\$Recycle.Bin\' + $sid

Get-Acl -LiteralPath $target |
    Select-Object Owner,AccessToString,AreAccessRulesProtected

Get-Acl -LiteralPath $recycleUser |
    Select-Object Owner,AccessToString,AreAccessRulesProtected

附录 B:参考文献

  1. Microsoft Sysinternals:Process Monitor:说明 Process Monitor 对文件系统、注册表、进程和线程活动的实时捕获能力,支持按路径、操作和结果筛选。
posted @ 2026-09-21 13:33  Vinpay  阅读(24)  评论(0)    收藏  举报