如果PowerShell脚本完全出现任何错误并发送脚本,则发送电子邮件

Hun*_*pos 8 powershell powershell-2.0 powershell-3.0

我最近一直在考虑的事情,我想要Stack Overflow的好人提供一些意见.

我在不同的日程表上运行了相当多的PowerShell脚本(使用任务计划程序).这些脚本通常会收集数据并将其存储在SQL表中.我会说我现在正在运行40-50个脚本,或许更多.

我最近认真考虑的一件事是最好的方法:

  1. 确保如果发生任何错误,脚本将退出而无需进一步处理.
  2. 该脚本还应该向我发送一封关于失败的电子邮件,其中包含异常详细信息,告诉我它有多远.
  3. 记录成绩单/进度,以便我可以查看任何错误并尝试更好地在脚本中处理它们.

这将是一项相当多的工作,所以我想从一开始就采用正确的方法.

我能看到实现这样的事情的唯一方法是做以下事情:

将$ ErrorActionPreference设置为"Stop"

这应该导致任何异常触发Try/Catch块.

在Try/Catch/Finally块中运行整个脚本.

最后,块当然是可选的.像这样的东西:

$ErrorActionPreference = "Stop"

Try
{
    $Content = gc "C:\Temp\NonExistentFile.txt"
    foreach ($Line in $Content)
    {
        Write-Host $Line
    }
}
Catch
{
    Write-Host $_ -ForegroundColor "Red" -BackgroundColor "Black"
    break
}
Run Code Online (Sandbox Code Playgroud)

将"Transcript"数据记录到HTML中,并在失败时通过电子邮件发送内容.

我尝试了几种日志记录方式,其中一个关键因素是我需要的东西是:

  1. 通过提供文本和日志文件位置轻松登录.
  2. 包括日志文件每行开头的日期/时间.

我开始将文本写入.txt文件,但这是一项工作要做.

Start-Transcript没问题,但没有在每行上包含日期/时间.

我使用Start-Transcript的自定义函数取得了一些成功,并将我发送到其中的任何文本写入Write-Host,每行开头的日期/时间.

但最终我认为我需要做的是登录.html文档,然后在发生错误时通过电子邮件发送内容.像这样的例子:

Function Send-ErrorEmail
{
    Write-Host "Would Send Email Here" -ForegroundColor "Magenta"
}

Function Write-Html
{
    [CmdletBinding()]
    param
    (
        [Parameter(ValueFromPipeline=$True)]$Text,
        $HTMLTag
    )

    [string]$CurrentDateTime = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss - ")

    switch ($HTMLTag)
    {
        "h1" {$ReturnText =  ("<h1>" + $Text + "</h1>")}
        "h2" {$ReturnText =  ("<h2>" + $Text + "</h2>")}
        default {$ReturnText = ("<p>" + $CurrentDateTime + $Text + "</p>")}
    }

    Write-Host -ForegroundColor "Yellow" ($CurrentDateTime + $Text)
    return $ReturnText
}

$ErrorActionPreference = "Stop"

Try
{
    #Stores the HTML File
    $LogfilePath = "C:\Temp\LogFile.html"

    #Begin HTML
    $HTML = @()
    $HTML += "<html><head></head><body>"
    $HTML += "Begin Script" | Write-Html

    #Loop through Computers
    $Computers = "LocalHost", "DoesNotExist", "127.0.0.1"
    foreach ($Computer in $Computers)
    {
        #Get Services
        $HTML += "Computer: $Computer" | Write-Html -HTMLTag "h1"
        $Services = Get-Service -Computer $Computer
        $HTML += $Services | ConvertTo-Html -Fragment
    }

    #Complete HTML
    $HTML += "Script End" | Write-Html
    $HTML += "</body></html>"
    $HTML | Out-File $LogfilePath
}
Catch
{
    #Add Exception to HTML
    $HTML += $_ | Out-String | Write-Html

    #Complete HTML
    $HTML += "</body></html>"
    $HTML | Out-File $LogfilePath

    #Send EMail
    Send-ErrorEmail

    #Exit Script
    exit
}
Run Code Online (Sandbox Code Playgroud)

有什么想法吗?你认为我可以改进吗?显然,没有CSS格式的HTML文档是丑陋的,而Send Mail函数没有做任何事情,但它似乎是做我想要的最简单的方法.

我当然可以点源所有脚本中的任何功能,以便于更改通知电子邮件地址或类似内容.

Kei*_*ill 10

对于全局错误处理,我更喜欢使用trap语句.

function ErrorHandler($error) 
{
    ... write out error info
    ... send email message with error info
    ... etc
}

trap { ErrorHandler $_; break }

... rest of script code
Run Code Online (Sandbox Code Playgroud)

如果你想保留任何错误,那么是的,设置$ErrorActionPreferenceStop.

  • 有趣的是,我更多地阅读了陷阱声明并遇到了这个问题,然后我意识到这就是你!:) http://rkeithhill.wordpress.com/2009/08/03/effective-powershell-item-16-dealing-with-errors/ - 我没有花很多时间在它上面,但它看起来像陷阱交互式调用时语句不能正常工作?我不能让你的倒数第二个例子来调用陷阱,除非我将它放入.ps1文件并执行它. (2认同)