Powershell下载SharePoint文件时如何跳过foreach循环错误与超时并记录日志
SPO下载脚本异常兼容优化方案
核心调整逻辑
- 缩小异常捕获范围:原脚本将整个函数逻辑包裹在同一个try/catch中,任意节点报错都会直接跳出函数逻辑。修改后将单个文件下载、单个子文件夹递归的逻辑单独做异常捕获,单个资源出错不影响剩余任务执行。
- 缩短请求超时时间:给SharePoint CSOM上下文设置更短的超时阈值,避免异常场景下长时间无响应。
- 新增错误日志落盘:所有异常对应的文件/文件夹路径、错误信息、发生时间都会自动写入指定TXT日志文件,方便后续排查。
完整修改后代码
Function Download-SPOFolder() { param ( [Parameter(Mandatory=$true)] [string] $SiteURL, [Parameter(Mandatory=$true)] [Microsoft.SharePoint.Client.Folder] $SourceFolder, [Parameter(Mandatory=$true)] [string] $TargetFolder ) #Create Local Folder, if it doesn't exist $FolderName = ($SourceFolder.ServerRelativeURL) -replace "/","\\" $LocalFolder = Join-Path $TargetFolder $FolderName If (!(Test-Path -Path $LocalFolder)) { New-Item -ItemType Directory -Path $LocalFolder | Out-Null } #Get all Files from the folder Try { $FilesColl = $SourceFolder.Files $Ctx.Load($FilesColl) $Ctx.ExecuteQuery() } Catch { $logMsg = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') | 无法获取文件夹文件列表 | 路径:$($SourceFolder.ServerRelativeURL) | 错误:$($_.Exception.Message)" Add-Content -Path $ErrorLogPath -Value $logMsg Write-Host -f Red $logMsg } #Iterate through each file and download Foreach($File in $FilesColl) { $TargetFile = Join-Path $LocalFolder $File.Name Try { #Download the file $FileInfo = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($Ctx,$File.ServerRelativeURL) $WriteStream = [System.IO.File]::Open($TargetFile,[System.IO.FileMode]::Create) $FileInfo.Stream.CopyTo($WriteStream) $WriteStream.Close() $WriteStream.Dispose() write-host -f Green "Downloaded File:"$TargetFile } Catch { $logMsg = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') | 文件下载失败 | 源路径:$($File.ServerRelativeURL) | 目标路径:$TargetFile | 错误:$($_.Exception.Message)" Add-Content -Path $ErrorLogPath -Value $logMsg Write-Host -f Red $logMsg # 清理残留流 if($WriteStream) { $WriteStream.Dispose() } # 跳过当前文件继续执行 Continue } } #Process Sub Folders Try { $SubFolders = $SourceFolder.Folders $Ctx.Load($SubFolders) $Ctx.ExecuteQuery() } Catch { $logMsg = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') | 无法获取子文件夹列表 | 路径:$($SourceFolder.ServerRelativeURL) | 错误:$($_.Exception.Message)" Add-Content -Path $ErrorLogPath -Value $logMsg Write-Host -f Red $logMsg Return } Foreach($Folder in $SubFolders) { If($Folder.Name -ne "Forms") { Try { #Call the function recursively Download-SPOFolder -SiteURL $SiteURL -SourceFolder $Folder -TargetFolder $TargetFolder } Catch { $logMsg = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') | 子文件夹处理失败 | 路径:$($Folder.ServerRelativeURL) | 错误:$($_.Exception.Message)" Add-Content -Path $ErrorLogPath -Value $logMsg Write-Host -f Red $logMsg Continue } } } } #Set parameter values $orgName="myOrgName" $admin="myUsrName" $SiteURL="myUrl" $FolderRelativeUrl="myFolderUrl" $TargetFolder="C:\\Temp" # 错误日志存储路径,可自行修改 $ErrorLogPath = "C:\Temp\SPODownloadErrors.txt" # 初始化错误日志目录和文件 $logDir = Split-Path $ErrorLogPath -Parent if(-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir | Out-Null } if(-not (Test-Path $ErrorLogPath)) { New-Item -ItemType File -Path $ErrorLogPath | Out-Null } #Setup Credentials to connect $cred = Get-Credential -UserName $admin -Message GlobalAdminLogin Connect-SPOService -Url https://$orgName-admin.sharepoint.com -Credential $cred $Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password) #Setup the context $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL) $Ctx.Credentials = $Credentials # 设置请求超时时间为10秒,单位为毫秒,可根据网络情况调整 $Ctx.RequestTimeout = 10 * 1000 #Get the Web $Web = $Ctx.Web $Ctx.Load($Web) $Ctx.ExecuteQuery() $Web.ServerRelativeUrl+$FolderRelativeUrl #Get the Folder $SourceFolder = $Web.GetFolderByServerRelativeUrl($Web.ServerRelativeUrl+$FolderRelativeUrl) $Ctx.Load($SourceFolder) $Ctx.ExecuteQuery() #Call the function to download Folder Download-SPOFolder -SiteURL $SiteURL -SourceFolder $SourceFolder -TargetFolder $TargetFolder
内容的提问来源于stack exchange,提问作者ICT_SGR8
相关产品推荐
相关产品推荐

