You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows系统中如何对被其他程序占用的文件执行写入操作?

实现思路(Rust优先)

前置要求

所有操作都需要程序以管理员权限运行,且开启SeDebugPrivilege特权,否则无法枚举系统全局句柄、访问其他进程资源。上述特权的Rust实现参考代码:

use winapi::um::securitybaseapi::{AdjustTokenPrivileges, LookupPrivilegeValueW};
use winapi::um::processthreadsapi::{OpenProcessToken, GetCurrentProcess};
use winapi::um::winnt::{SE_DEBUG_NAME, SE_PRIVILEGE_ENABLED, TOKEN_ADJUST_PRIVILEGES, TOKEN_QUERY};
use winapi::um::handleapi::CloseHandle;

unsafe fn enable_debug_privilege() -> bool {
    let mut token = std::ptr::null_mut();
    if OpenProcessToken(
        GetCurrentProcess(),
        TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
        &mut token,
    ) == 0 {
        return false;
    }

    let mut luid = std::mem::zeroed();
    if LookupPrivilegeValueW(std::ptr::null(), SE_DEBUG_NAME, &mut luid) == 0 {
        CloseHandle(token);
        return false;
    }

    let mut tp = winapi::um::winnt::TOKEN_PRIVILEGES {
        PrivilegeCount: 1,
        Privileges: [winapi::um::winnt::LUID_AND_ATTRIBUTES {
            Luid: luid,
            Attributes: SE_PRIVILEGE_ENABLED,
        }],
    };

    let ret = AdjustTokenPrivileges(
        token, 
        0, 
        &mut tp, 
        std::mem::size_of_val(&tp) as u32, 
        std::ptr::null_mut(), 
        std::ptr::null_mut()
    );
    CloseHandle(token);
    ret != 0 && winapi::um::errhandlingapi::GetLastError() == 0
}

步骤1:查找目标文件对应的句柄

核心依赖ntapi和winapi两个crate,实现逻辑如下:

  • 调用NtQuerySystemInformation,传入SystemHandleInformation(值为16)参数,获取系统全局所有句柄的列表,注意需要动态调整缓冲区大小直到API返回成功
  • 遍历所有句柄,筛选类型为File的句柄:先调用OpenProcess打开句柄所属进程,获取PROCESS_DUP_HANDLE权限,再调用DuplicateHandle将目标进程的句柄复制到当前进程
  • 对复制到当前进程的句柄调用GetFinalPathNameByHandleW,获取对应的文件绝对路径,和你要操作的目标文件路径匹配,匹配成功则记录该句柄所属的进程ID、原句柄值

注意:NtQuerySystemInformation属于Windows未公开的Native API,不同Windows版本的结构体定义、参数可能存在差异,使用时需要做好多版本兼容测试。

步骤2:强制关闭跨进程文件句柄

无需远程注入目标进程,直接调用DuplicateHandle传入指定标志即可关闭目标进程的句柄,Rust实现逻辑:

  • 调用OpenProcess打开目标进程,获取PROCESS_DUP_HANDLE权限
  • 调用DuplicateHandle,参数依次传入:目标进程句柄、要关闭的源句柄值、当前进程句柄、空指针接收新句柄、0、FALSE、DUPLICATE_CLOSE_SOURCE(值为1)标志
  • 调用成功后,目标进程内的对应文件句柄会被直接关闭

强制关闭句柄后目标程序的行为

程序后续对已关闭的句柄执行任何读写、刷新、关闭操作时,都会收到ERROR_INVALID_HANDLE(错误码6)的报错,具体表现取决于程序自身的错误处理逻辑:

  • 记事本:记事本打开文件时会将全部内容读取到内存,打开完成后就不再使用原句柄,直到用户触发保存操作。强制关闭其句柄后,记事本当前编辑的内容不会受影响,用户点击保存时会重新打开文件获取新句柄写入,会直接覆盖你对原文件做出的修改,不会触发报错。
  • Word:Word打开文件后会长期持有文件句柄,且会定期执行自动保存、元数据同步、临时文件校验等后台操作。强制关闭其句柄后,大概率会立刻弹出文件访问错误的提示,用户点击保存时会直接失败,部分版本会要求用户另存为新文件,不会覆盖你对原文件的修改,极端情况下会出现程序崩溃。
  • 其他流式读取类程序(如视频播放器、日志采集工具):关闭句柄后会直接中断当前读取操作,弹出文件读取失败的提示。

内容的提问来源于stack exchange,提问作者thegrinderguy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 04:45:04