我有一个Powershell脚本可以自动执行流程并通过电子邮件发送报告。
Send-MailMessage -To $toAddress -From "no-reply@domain.org" -subject "Automation status" -body $bodystr -SmtpServer SERVER1 -EA Stop
所以$bodystr
本质上是整个脚本中的附加字符串,用于报告发生的事情并且有多行。比如:
$bodystr = $bodystr + "Line found: 305`n"
$bodystr = $bodystr + "Moving line 305 to 574`n"
Send-MailMessage
命令位于任何函数之外的脚本底部。但是大多数其他代码都有各种不同的功能。
问题是$bodystr
似乎无法在函数内部访问,因此电子邮件缺少大量信息。
我相信我可以使用Set-Variable
或传递参数,但是有太多的参数似乎离每个函数添加一个新参数只是为了保持字符串更新的最佳实践。
处理此问题的最佳做法是什么?
答案 0 :(得分:3)
作为一般规则,不要将数据写回函数范围之外的变量。
如果您是通过从多个来源收集数据来编译电子邮件,请将其抽象为多个函数,每个函数执行一项操作,并让它们返回带有相关输出的多行字符串。
在脚本结束时,收集不同的邮件正文部分,并在发送之前将它们连接到单个字符串。
在这个例子中,我们有一个脚本,它接受一个日志文件的路径,定义一个从日志文件中提取错误的函数,并发送一个包含正文错误的电子邮件:
param(
[ValidateScript({Test-Path $_ -PathType Leaf })]
[string]$LogPath = 'C:\Path\To\File.log',
[string]$From = 'noreply@company.example',
[string]$To = @('ceo@company.example','finance@company.example'),
[string]$Subject = 'Super Important Weekly Report',
[string]$SmtpServer = $PSEmailServer,
[string]$Credential
)
# Define functions with a straight forward purpose
# e.g. Searching a logfile for errors
function Parse-Logfile {
param($LogPath)
[string[]]$LogErrors = @()
Get-Content $LogPath |ForEach-Object{
if($_ -contains $Error){
$LogErrors += $_
}
}
# Create and return a custom object has the error details as properties
New-Object psobject -Property @{
ErrorCount = $LogErrors.Count
Errors = $LogErrors
}
}
# Create a email template that's easy to maintain
# You could store this in a file and add a $TemplateFile parameter to the script ;-)
$EmailTemplate = @'
Hi there!
Found {0} errors in log file: {1}
{2}
Regards
Zeno
'@
# Use your function(s) to create and gather the details you need
$ErrorReport = Parse-Logfile -LogPath $LogPath
# If necessary, concatenate strings with -join
$ErrorString = $ErrorReport.Errors -join "`n"
# Use the format operator to the final Body string
$Body = $EmailTemplate -f $ErrorReport.ErrorCount, $LogPath, $ErrorString
# Set up a splatting table (Get-Help about_Splatting)
$MailParams = @{
To = $To
From = $From
Subject = $Subject
Body = $Body
SmtpServer = $SmtpServer
}
if($PSBoundParameters.ContainsKey('Credential')){
$MailParams['Credential'] = $Credential
}
# Send mail
Send-MailMessage @MailParams