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

时间:2013-01-09 21:08:39

标签: powershell powershell-v2.0 powershell-v3.0

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

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

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

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

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

    将$ ErrorActionPreference设置为“停止”

    这会导致任何异常触发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
    }
    

    将“脚本”数据记录到HTML中,并在失败时通过电子邮件发送内容。

    我尝试过几种记录方式,对我来说关键之一就是我需要的东西是:

    1. 通过提供文本和日志文件位置轻松登录。
    2. 在日志文件的每一行开头包含日期/时间。
    3. 我开始将文本写入.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
      }
      

      有什么想法?你认为我可以改进吗?显然,没有CSS格式的HTML文档很难看,发送邮件功能没有做任何事情,但它似乎是做我想要的最简单的方法。

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

1 个答案:

答案 0 :(得分:10)

对于全局错误处理,我更喜欢使用陷阱语句。

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

trap { ErrorHandler $_; break }

... rest of script code

如果您想保留任何错误,那么请将$ErrorActionPreference设置为Stop