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

PowerShell查找密码保护PDF并移动文件夹时文件锁定问题求助

问题原因

OpenText()方法返回的StreamReader对象没有被显式释放,持有的文件句柄会一直保留到PowerShell垃圾回收自动清理,时机晚于移动操作执行,导致文件占用报错。

可行解决方案

方案1:使用[System.IO.File]::ReadAllText()(推荐)

该静态方法读完文件后会自动释放所有资源,不需要手动处理句柄,修改后完整代码如下:

$Source = 'sourcefolder'
$Dest = 'Destinationfolder'
        
Get-ChildItem -Path $Source -Directory | ForEach-Object {
    $hasEncryptedPdf = Get-ChildItem -Path $_.FullName -Filter *.pdf -File | Where-Object {
        [System.IO.File]::ReadAllText($_.FullName).Contains("Encrypt")
    } | Measure-Object | Select-Object -ExpandProperty Count

    if ($hasEncryptedPdf -gt 0) {
        Move-Item -Path $_.FullName -Destination $Dest -Force -Verbose
    }
}

方案2:使用using块管理StreamReader

如果要保留原有的StreamReader用法,用using块自动释放对象,退出块后文件锁会立即解除:

$Source = 'sourcefolder'
$Dest = 'Destinationfolder'
        
Get-ChildItem -Path $Source -Directory | ForEach-Object {
    If (Get-ChildItem -Path $_.FullName -Filter *.pdf | Where-Object { 
            $isEncrypted = $false
            using ($reader = $_.OpenText()) {
                $isEncrypted = $reader.ReadToEnd().Contains("Encrypt")
            }
            return $isEncrypted
        }) {
        Move-Item -Path $_.FullName -Destination $Dest -Force -Verbose
    }
}

优化建议

如果需要处理大体积PDF,可以只读取文件头部1024字节判断(PDF加密标记通常在文件头范围内),大幅降低IO开销:

# 替换Where-Object内的判断逻辑即可
Where-Object {
    $header = [byte[]]::CreateInstance([byte], 1024)
    using ($fs = [System.IO.File]::OpenRead($_.FullName)) {
        $fs.Read($header, 0, $header.Length) | Out-Null
    }
    return [System.Text.Encoding]::ASCII.GetString($header).Contains("Encrypt")
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 08:30:02