powershell - 如何在此 PowerShell 脚本中产生错误
问题描述
有人可以告诉我,我怎样才能产生错误并在日志文件中捕获它?因为我想测试这个脚本的错误视角但无法得到它,如果你能让我知道如何手动测试这个脚本以获得错误视角,这将非常有帮助。
让我向你描述一下我通过这个脚本实现了什么。因为我想使用文件命名约定将文件移动到服务器上的各个文件夹并备份到现有文件(如果有的话),并且在整个过程生成 CSV 中的日志文件并发送一封包含成功或错误消息的电子邮件。
$Source = 'c:\uploadtool\' # Source Location
$RetailSource = 'Retail P&C Sales Intelligence\*'
$GroupSource = 'Group P&C Sales Intelligence\*'
$UATSource = 'UAT\*'
$RetailDest = 'D:\ToolUpload\Retail-EIP' # 1st Destination Location
$GroupDest = 'D:\ToolUpload\Group-EIP' # 2nd Destination location
$UATDest ='D:\ToolUpload\UAT' # Added 3rd destination location in this version 1.7.2V
$ArchiveData = 'D:\Backup\backup_{0:yyyyMMddHHmm}' -f (Get-Date)
$LogFolder = 'D:\logs'
# because of your wish to get a Table-style log, use CSV format you can open in Excel
$LogFile = 'D:\logs\uploadlog_{0:yyyyMMdd}.csv'-f (Get-Date)
$Sourcetest = Test-Path -Path '$RetailSource','$GroupSource' -PathType Leaf
#Email Params:
$EmailParams = @{
SmtpServer ='xyz.smtp.com'
Port = '25'
Subject ='File Upload Status'
To ="xyz@xyz.com"
From ="no-xyz@xyz.com"
}
# make sure the output LogFolder exist
# by adding the -Force switch there is no need to use Test-Path first, because if
# the folder already exists, the cmdlet will return the DirectoryInfo of that,
# otherwise it will create a new folder. Since we don't want output, we use $null = ..
$null = New-Item -Path $LogFolder -ItemType Directory -Force
# loop through the files in the source folder and collect the outputted objects
$result =
Get-ChildItem -Path "$Source" -Include '*Group-EIP*', '*Retail-EIP*','*UAT*' -File -Force -Recurse |
ForEach-Object {
Write-Host "Processing file '$($_.FullName)'"
# create an object with (for now) 3 empty properties
$out = $_ |
Select-Object @{Name = 'Date'; Expression = {(Get-Date)}},
@{Name = 'Source'; Expression = {$_.FullName}},
@{Name = 'FileSize'; Expression = {$_.Length}},
Destination, # depends on the file name
@{Name = 'Archive'; Expression = {$ArchiveData}}, # initialize to Not Applicable
Result
# depending on its name, get the correct destination folder
$destFolder = if($_.Name -match "Retail-EIP") { $RetailDest } elseif($_.Name -match "Group-EIP") { $GroupDest } else {$UATDest}
# create the backup destination folder if it didn't already exist
# the first file in column 'Source' is now responsible for creating the backup folder
$null = New-Item -Path $destFolder -ItemType Directory -Force
# get the full path and filename for the destination
$existingFile = Join-Path -Path $destFolder -ChildPath $_.Name
# add the destination folder to the output object
$out.Destination = $destFolder
try
{ # if a file with that name already exists in the destination, move it to the Archive folder
if (Test-Path -Path $existingFile -PathType Leaf) {
# create the Archive folder if it didn't already exist
$null = New-Item -Path $ArchiveData -ItemType Directory -Force
Move-Item -Path $existingFile -Destination $ArchiveData -ErrorAction Stop
# add the archived file to the output object
$out.Archive = $existingFile
Write-Host "File '$existingFile' has been backed-up to '$ArchiveData'"
}
# next move the file from the source folder to its destination (either $RetailDest or $GroupDest)
$_ | Move-Item -Destination $destFolder -ErrorAction Stop
$out.Result = 'OK'
Write-Host "File '$($_.FullName)' has been moved to '$destFolder'"
$Body = " The File '$($_.FullName)' has been moved to '$destFolder' 'n Size of the file is '$($_.Length)' `n file has been backed up on the location '$ArchiveData' "
}
catch
{ # ouch.. something went horribly wrong on a Move-Item action
$Body = " Error occured trying to move the file '$($_.FullName)' to '$destFolder. `n$($_.Exception.Message)"
Write-Warning "An error occurred: $_.Exception.Message"
$out.Result = "Error: $($_.Exception.Message)" | Add-Content -Path $LogFile -Force
}
Send-MailMessage @EmailParams -Body $Body
# output the object so it gets collected in variable $result
$out
}
# now you can save the results as structured CSV file to open in Excel
$result | Export-Csv -Path $LogFile -UseCulture -NoTypeInformation -Append -Force
# and display on the screen using Out-GridView as the data will probably be too wide for Format-Table
$result | Out-GridView -Title 'Backup results'
解决方案
好的,我已经修改了您的代码并在其中添加了一些注释,希望能指出您的代码中的错误。
正如我从您之前的问题中收集到的,您还想报告具有“错误”文件名的文件(即不包含“Group-EIP”、“Retail-EIP”或“UAT”)。
当您将参数添加-Include '*Group-EIP*', '*Retail-EIP*','*UAT*'
到 Get-ChildItem cmdlet 时,所有具有错误名称的文件甚至都不会进入 ForEach 循环,并且您将无法将它们记录为“错误:文件名不正确”,因此请将其删除。
接下来,所有这些的输出是一个结构化的 CSV 文件,并且您Add-Content -Path $LogFile -Force
在代码中添加了一个点,这将破坏结构并使 CSV 无法使用。
您在循环中添加了一个 Send-MailMessage 调用,通过这样做,代码将在它处理的每个文件上发送一封电子邮件。我已将其移至代码末尾,因此它只会发送一封电子邮件。
对于演示,我将生成的 CSV 文件作为附件添加到这封电子邮件中,但您也可以创建一个漂亮的 HTML 表格,其中包含您在$result
.
我将把它留给你,但在 StackOverflow 上可以找到很多例子。
$RetailSource = Join-Path -Path 'c:\uploadtool' -ChildPath 'Retail P&C Sales Intelligence'
$GroupSource = Join-Path -Path 'c:\uploadtool' -ChildPath 'Group P&C Sales Intelligence'
$UATSource = Join-Path -Path 'c:\uploadtool' -ChildPath 'UAT'
####################################################################################
# now group these paths into a single array variable as I have shown you in my answer
# here: https://stackoverflow.com/a/67673422/9898643
####################################################################################
$Source = $RetailSource, $GroupSource, $UATSource
$RetailDest = 'D:\ToolUpload\Retail-EIP' # 1st Destination Location
$GroupDest = 'D:\ToolUpload\Group-EIP' # 2nd Destination location
$UATDest = 'D:\ToolUpload\UAT' # Added 3rd destination location in this version 1.7.2V
$ArchiveData = 'D:\Backup\backup_{0:yyyyMMddHHmm}' -f (Get-Date)
$LogFolder = 'D:\logs'
# because of your wish to get a Table-style log, use CSV format you can open in Excel
$LogFile = 'D:\logs\uploadlog_{0:yyyyMMdd}.csv'-f (Get-Date)
# make sure the output LogFolder exist
# by adding the -Force switch there is no need to use Test-Path first, because if
# the folder already exists, the cmdlet will return the DirectoryInfo of that,
# otherwise it will create a new folder. Since we don't want output, we use $null = ..
$null = New-Item -Path $LogFolder -ItemType Directory -Force
# loop through the files in the source folders and collect the outputted objects.
####################################################################################
# $Source is an ARRAY of paths, so do not surround it with quotes!
# If you want to also log files that have a bad name, DO NOT USE
# -Include '*Group-EIP*', '*Retail-EIP*','*UAT*', otherwise these files are ignored!
####################################################################################
$result = Get-ChildItem -Path $Source -File -Force -Recurse | ForEach-Object {
Write-Host "Processing file '$($_.FullName)'"
# create an object with (for now) 2 empty properties
$out = $_ | Select-Object @{Name = 'Date'; Expression = {(Get-Date)}},
@{Name = 'Source'; Expression = {$_.FullName}},
@{Name = 'FileSize'; Expression = {$_.Length}},
Destination, # depends on the file name
@{Name = 'Archive'; Expression = {$ArchiveData}},
Result
# test if the file has a correct name
if ($_.BaseName -notmatch 'Group-EIP|Retail-EIP|UAT') {
# file does not have the correct naming convention
$out.Archive = $null
$out.Result = "Error: Incorrect filename"
}
else {
# depending on its name, get the correct destination folder
$destFolder = if($_.Name -match "Retail-EIP") { $RetailDest } elseif($_.Name -match "Group-EIP") { $GroupDest } else { $UATDest }
# create the backup destination folder if it didn't already exist
# the first file in column 'Source' is now responsible for creating the backup folder
$null = New-Item -Path $destFolder -ItemType Directory -Force
# get the full path and filename for the destination
$existingFile = Join-Path -Path $destFolder -ChildPath $_.Name
# add the destination folder to the output object
$out.Destination = $destFolder
try {
# if a file with that name already exists in the destination, move it to the Archive folder
if (Test-Path -Path $existingFile -PathType Leaf) {
# create the Archive folder if it didn't already exist
$null = New-Item -Path $ArchiveData -ItemType Directory -Force
Move-Item -Path $existingFile -Destination $ArchiveData -ErrorAction Stop
# add the archived file to the output object
$out.Archive = $existingFile
Write-Host "File '$existingFile' has been backed-up to '$ArchiveData'"
}
# next move the file from the source folder to its destination (either $RetailDest or $GroupDest)
$_ | Move-Item -Destination $destFolder -ErrorAction Stop
$out.Result = 'OK'
Write-Host "File '$($_.FullName)' has been moved to '$destFolder'"
}
catch { # ouch.. something went horribly wrong on a Move-Item action
Write-Warning "An error occurred: $_.Exception.Message"
$out.Result = "Error: $($_.Exception.Message)"
####################################################################
# $LogFile will be saved later as CSV, Do not ruin the structure
# by inserting '| Add-Content -Path $LogFile -Force'
####################################################################
}
}
# output the object so it gets collected in variable $result
$out
}
# now you can save the results as structured CSV file to open in Excel
$result | Export-Csv -Path $LogFile -UseCulture -NoTypeInformation -Append -Force
# and display on the screen using Out-GridView as the data will probably be too wide for Format-Table
$result | Out-GridView -Title 'Backup results'
# and send an email with the resulting CSV file as attachment
# or create a nice HTML table from the objects in $result and put that in the body.
# Lots of examples for that can be found on SO
$EmailParams = @{
SmtpServer = 'xyz.smtp.com'
Port = '25'
Subject = 'File Upload Status'
To = "xyz@xyz.com"
From = "no-xyz@xyz.com"
Body = "Please see attached logfile"
Attachments = $LogFile
}
Send-MailMessage @EmailParams
推荐阅读
- android - 在 Flutter Legacy App 上初始化 Firebase 时出现问题(仅限 Android)
- css - 如何在悬停时定位scss中的后缀
- java - 如何从字符串实体中检索指定数据
- python - 合并具有相同时间戳的多行并将值放入新列
- c# - 使用 Azure 功能管理器与“true”和“false”的常规配置值相比有什么好处
- python - Python3:如何编写用于模拟类方法的单元测试的装饰器
- r - RStata - 'RStata.log':没有这样的文件或目录
- c# - 使用表达式数组中的索引获取 lambda 表达式的名称
- python - 字典列表删除半出现
- python - 标准化网页进度