PowerShell脚本Catch块无法捕获非法上传文件错误及日志格式化问题
PowerShell脚本调整方案
问题1:Catch块无法捕获错误的修复原因
- PowerShell默认情况下cmdlet产生的非终止错误不会触发catch逻辑,需要给涉及文件操作的命令添加
-ErrorAction Stop参数,将错误转为终止错误才能被捕获 - 原有逻辑中不符合
Retail-EIP/Group-EIP匹配规则的文件不会进入任何执行分支,不会抛出任何错误,自然也不会被catch捕获,需要补充else分支主动上报不匹配的错误 - 原有备份逻辑存在隐患:每次循环都会移动目标目录下的所有文件,仅需备份和当前上传文件同名的已有文件即可,避免误操作
问题2:日志改为表格格式的实现
采用CSV格式存储日志,CSV天然为结构化表格格式,支持Excel、WPS等工具直接打开查看,不需要手动拼接表格格式,每一条日志都包含固定的字段:操作时间、操作类型、关联文件名、操作状态、备注信息。
修改后的完整代码
# 基础路径配置 $Source = 'c:\uploadtool\*' # 源文件路径 $RetailDest = "D:\ToolUpload\Retail-EIP" # Retail目标路径 $GroupDest = "D:\ToolUpload\Group-EIP" # Group目标路径 $Backupdata = "D:\Backup" # 根备份目录 $lognamefolder = "D:\logs" # 日志改为CSV格式,支持表格查看 $logname = "D:\logs\uploadlog_$(Get-Date -Format 'yyyyMMdd').csv" # 初始化日志目录和日志文件 if (-not (Test-Path -Path $lognamefolder)) { New-Item -Path $lognamefolder -ItemType Directory | Out-Null } # 日志文件不存在则创建并写入表头 if (-not (Test-Path -Path $logname -PathType Leaf)) { "操作时间,操作类型,关联文件名,操作状态,备注" | Out-File -Path $logname -Encoding utf8 } # 初始化本次备份目录 $ArchiveData = New-Item -Path "$Backupdata\backup_$(Get-Date -Format 'yyyyMMddHHmm')" -Force -ItemType Directory # 获取源目录所有文件 $sourceFiles = Get-ChildItem -Path $Source -File -Force -Recurse # 写入启动日志 [PSCustomObject]@{ 操作时间 = Get-Date -Format 'yyyy-MM-dd HH:mm:ss' 操作类型 = "任务启动" 关联文件名 = "" 操作状态 = "成功" 备注 = "本次待处理文件共$($sourceFiles.Count)个" } | Export-Csv -Path $logname -Append -Encoding utf8 -NoTypeInformation foreach ($file in $sourceFiles) { try { $fname = $file.FullName $fileName = $file.Name if ($file.Name -match "Retail-EIP") { # 仅备份目标路径下和当前文件同名的已有文件 $targetFile = Join-Path -Path $RetailDest -ChildPath $fileName if (Test-Path -Path $targetFile) { Move-Item -Path $targetFile -Destination $ArchiveData -Force -ErrorAction Stop # 写入备份成功日志 [PSCustomObject]@{ 操作时间 = Get-Date -Format 'yyyy-MM-dd HH:mm:ss' 操作类型 = "文件备份" 关联文件名 = $fileName 操作状态 = "成功" 备注 = "备份路径:$ArchiveData" } | Export-Csv -Path $logname -Append -Encoding utf8 -NoTypeInformation } # 上传新文件到目标路径 Move-Item -Path $fname -Destination $RetailDest -Force -ErrorAction Stop # 写入上传成功日志 [PSCustomObject]@{ 操作时间 = Get-Date -Format 'yyyy-MM-dd HH:mm:ss' 操作类型 = "文件上传" 关联文件名 = $fileName 操作状态 = "成功" 备注 = "目标路径:$RetailDest" } | Export-Csv -Path $logname -Append -Encoding utf8 -NoTypeInformation } elseif ($file.Name -match "Group-EIP") { # 仅备份目标路径下和当前文件同名的已有文件 $targetFile = Join-Path -Path $GroupDest -ChildPath $fileName if (Test-Path -Path $targetFile) { Move-Item -Path $targetFile -Destination $ArchiveData -Force -ErrorAction Stop # 写入备份成功日志 [PSCustomObject]@{ 操作时间 = Get-Date -Format 'yyyy-MM-dd HH:mm:ss' 操作类型 = "文件备份" 关联文件名 = $fileName 操作状态 = "成功" 备注 = "备份路径:$ArchiveData" } | Export-Csv -Path $logname -Append -Encoding utf8 -NoTypeInformation } # 上传新文件到目标路径 Move-Item -Path $fname -Destination $GroupDest -Force -ErrorAction Stop # 写入上传成功日志 [PSCustomObject]@{ 操作时间 = Get-Date -Format 'yyyy-MM-dd HH:mm:ss' 操作类型 = "文件上传" 关联文件名 = $fileName 操作状态 = "成功" 备注 = "目标路径:$GroupDest" } | Export-Csv -Path $logname -Append -Encoding utf8 -NoTypeInformation } else { # 匹配不到规则主动抛出错误 throw "文件不符合Retail-EIP/Group-EIP命名匹配规则,跳过上传" } } catch { # 捕获所有错误写入日志 [PSCustomObject]@{ 操作时间 = Get-Date -Format 'yyyy-MM-dd HH:mm:ss' 操作类型 = "操作异常" 关联文件名 = $file.Name 操作状态 = "失败" 备注 = $_.Exception.Message } | Export-Csv -Path $logname -Append -Encoding utf8 -NoTypeInformation } } # 写入任务结束日志 [PSCustomObject]@{ 操作时间 = Get-Date -Format 'yyyy-MM-dd HH:mm:ss' 操作类型 = "任务结束" 关联文件名 = "" 操作状态 = "完成" 备注 = "所有文件处理完成" } | Export-Csv -Path $logname -Append -Encoding utf8 -NoTypeInformation
代码改动说明
- 所有文件操作命令添加
-ErrorAction Stop,确保所有操作错误都能被catch捕获 - 补充了不符合匹配规则的文件的错误抛出逻辑,所有异常都会被记录到日志
- 日志改为CSV结构化表格格式,所有字段统一,直接用Excel打开即可查看表格效果
- 修复原有备份逻辑的bug,不再每次移动目标目录所有文件,仅备份当前上传对应的同名文件
- 所有日志采用结构化对象写入,避免格式混乱
内容的提问来源于stack exchange,提问作者essex lake
相关产品推荐
相关产品推荐

