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

执行Set-PnPListItem时随机出现文件被修改错误的解决咨询

解决SharePoint文件更新随机冲突的方案

核心问题分析

这个随机报错是典型的并发冲突——脚本在执行「检查文件存在」到「执行更新」的间隙里,文件被其他操作改动了。可能的触发场景包括:SharePoint后台索引/同步任务、其他用户或脚本的修改,甚至虚拟机环境里的多实例脚本运行,都会导致你的更新操作因版本不匹配被拒绝。

具体解决步骤

1. 用ETag做版本验证,避免盲更新

获取文件时同时拿到它的ETag值,更新时带上这个标识,确保文件在检查后没被改动:

$file = Get-PnPFile -Url $fileUrl -AsListItem
$originalETag = $file["ETag"]

try {
    Set-PnPListItem -List $listId -Identity $file.Id -Values $updateValues -ETag $originalETag
}
catch [Microsoft.SharePoint.Client.ServerException] {
    if ($_.Exception.Message -match "has been modified") {
        Write-Host "文件已被修改,重新获取最新信息后重试..."
        $newFile = Get-PnPFile -Url $fileUrl -AsListItem
        Set-PnPListItem -List $listId -Identity $newFile.Id -Values $updateValues
    }
    else {
        throw $_
    }
}

如果是独占更新场景,也可以用签出锁定文件:

Checkout-PnPFile -Url $fileUrl
try {
    Set-PnPListItem -List $listId -Identity $file.Id -Values $updateValues
}
finally {
    Checkin-PnPFile -Url $fileUrl -CheckinType MajorCheckIn -Comment "脚本自动更新"
}

2. 给更新逻辑加自动重试

既然错误是随机的,给操作加重试机制,最多重试3次(可调整):

$retryCount = 0
$maxRetries = 3
$updateSuccess = $false

while (-not $updateSuccess -and $retryCount -lt $maxRetries) {
    try {
        $file = Get-PnPFile -Url $fileUrl -AsListItem
        Set-PnPListItem -List $listId -Identity $file.Id -Values $updateValues
        $updateSuccess = $true
    }
    catch [Microsoft.SharePoint.Client.ServerException] {
        if ($_.Exception.Message -match "has been modified") {
            $retryCount++
            Write-Host "第$retryCount次重试更新文件..."
            Start-Sleep -Seconds 2 # 等2秒再试,给后台操作留时间
        }
        else {
            throw $_
        }
    }
}

if (-not $updateSuccess) {
    Write-Error "重试$maxRetries次后仍无法更新:$fileUrl"
}

3. 排查虚拟机环境的并发隐患

  • 检查虚拟机上是否有多个脚本实例同时运行:比如定时任务重复触发、误开多个PowerShell窗口,用任务管理器确认进程数量。
  • 定时任务的执行间隔要足够长,避免前一次脚本还没跑完,下一次又启动。
  • 查看文档库的版本历史:如果报错时的修改者是系统账户,大概率是SharePoint后台索引/同步任务在运行,避开这些时间段执行脚本。

4. 优化检查-更新的原子性

把「检查文件存在」和「更新」的两步逻辑改成先尝试更新,捕获“文件不存在”的错误再执行上传,减少中间的时间间隙:

try {
    # 先尝试更新,文件不存在会触发报错
    $file = Get-PnPFile -Url $fileUrl -AsListItem -ErrorAction Stop
    Set-PnPListItem -List $listId -Identity $file.Id -Values $updateValues
}
catch [Microsoft.SharePoint.Client.ServerException] {
    if ($_.Exception.Message -match "File not found") {
        # 文件不存在,执行上传
        Add-PnPFile -Path $localFilePath -Folder $folderUrl
        # 上传后再设置列数据
        $newFile = Get-PnPFile -Url $fileUrl -AsListItem
        Set-PnPListItem -List $listId -Identity $newFile.Id -Values $updateValues
    }
    elseif ($_.Exception.Message -match "has been modified") {
        # 冲突处理:重新获取文件后重试更新
        $newFile = Get-PnPFile -Url $fileUrl -AsListItem
        Set-PnPListItem -List $listId -Identity $newFile.Id -Values $updateValues
    }
    else {
        throw $_
    }
}

额外注意事项

  • 确保PnP PowerShell模块是最新版本,旧版本可能存在并发处理bug:执行Update-Module -Name PnP.PowerShell更新。
  • 如果文档库开启了必填列或内容审批,后台验证可能临时锁定文件,更新时要确保所有必填字段都正确填充。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 11:34:52