执行Set-PnPListItem时随机出现文件被修改错误的解决咨询
核心问题分析
这个随机报错是典型的并发冲突——脚本在执行「检查文件存在」到「执行更新」的间隙里,文件被其他操作改动了。可能的触发场景包括: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
相关产品推荐
相关产品推荐

