Powershell 使用Try-Catch记录错误,即使发生错误也要发送摘要电子邮件

Powershell 使用Try-Catch记录错误,即使发生错误也要发送摘要电子邮件,powershell,Powershell,我希望这不是一个“你不能既吃蛋糕又吃蛋糕”的场景 目前: 脚本运行,对sources.csv中的所有对象执行try/catch,为每个失败的对象生成错误日志。除非所有对象都成功,否则不发送电子邮件 尝试: 脚本运行,对sources.csv中的所有对象执行try/catch,为每个失败的对象生成错误日志。发送显示发生了多少错误的电子邮件,并附加所有相关日志文件 $clientID = "Blargh Inc" $intelDir = "C:\Threat Intelligence" $webcl

我希望这不是一个“你不能既吃蛋糕又吃蛋糕”的场景

目前:

脚本运行,对sources.csv中的所有对象执行try/catch,为每个失败的对象生成错误日志。除非所有对象都成功,否则不发送电子邮件

尝试:

脚本运行,对sources.csv中的所有对象执行try/catch,为每个失败的对象生成错误日志。发送显示发生了多少错误的电子邮件,并附加所有相关日志文件

$clientID = "Blargh Inc"
$intelDir = "C:\Threat Intelligence"
$webclient = New-Object System.Net.WebClient
$intelSource = "$($intelDir)\sources.csv"
$intelCount = 0
$intelError = 0

# Begin Email Options
$body = "Threat Intelligence Feed ran for $clientID - "
$subject = "$($clientID) - Threat Intelligence - "
$email = @{
From = "me@mycompany.com"
To = "me@mycompany.com","notme@mycompany.com"
Subject = $subject
SMTPServer = "mail-server.office365.com"
Body = $body
}
# End Email Options

import-Csv $intelSource -ErrorAction SilentlyContinue | ForEach-Object {
        $storageDir = "$($intelDir)\$($_.threatType) $($_.threatSubtype)"
        $threat = $_.threatType + "_" + $_.threatSubtype    # Set this variable to save headaches passing it later
        $storageFile = "$($storageDir)\$($threat)_$($(get-date -f MM-dd-yy)).csv"    # Filename specified by sources.csv fields and today's date
        $url = $_.threatLocation
        # Begin Error Logging
        try {
            $intelCount++
            $webclient.DownloadFile($url,$storageFile)
        }
        catch {
            $intelError++
            $intelErrorMessage = $_.Exception|format-list -force
            echo $intelErrorMessage | Out-File $intelDir\$threat"_ErrorLog_"$(get-date -f MM-dd-yy).txt -Append
            Continue
        }
        # End Error Logging
        # Cleanup
        finally {
            $webclient.Dispose()
        }
        # Throttling (mainly future use with multiple sources)
        Start-Sleep 5
        }
如果出现任何错误,则未处理的零件:

if ($intelError -gt 0) {
    $email.Item('Subject') += "$($intelError) Error(s)"
    $email.Item('Body') += "$($intelError) of $($intelCount) sources failed. See attached error log(s)"
    Get-ChildItem -Path $intelDir | Where {$_.Name -match "$($(get-date -f MM-dd-yy))"} | foreach{$_.fullname} | Send-MailMessage @email
}
else {
    $email.Item('Subject') += "Success"
    $email.Item('Body') += "No errors"
    Send-MailMessage @email
}
评论后添加:

将现有代码包装到另一个
块中,然后将电子邮件代码放入该
块中:

try {
    import-Csv $intelSource -ErrorAction SilentlyContinue | ForEach-Object {
            $storageDir = "$($intelDir)\$($_.threatType) $($_.threatSubtype)"
            $threat = $_.threatType + "_" + $_.threatSubtype    # Set this variable to save headaches passing it later
            $storageFile = "$($storageDir)\$($threat)_$($(get-date -f MM-dd-yy)).csv"    # Filename specified by sources.csv fields and today's date
            $url = $_.threatLocation
            # Begin Error Logging
            try {
                $intelCount++
                $webclient.DownloadFile($url,$storageFile)
            }
            catch {
                $intelError++
                $intelErrorMessage = $_.Exception|format-list -force
                echo $intelErrorMessage | Out-File $intelDir\$threat"_ErrorLog_"$(get-date -f MM-dd-yy).txt -Append
                Continue
            }
            # End Error Logging
            # Cleanup
            finally {
                $webclient.Dispose()
            }
            # Throttling (mainly future use with multiple sources)
            Start-Sleep 5
            }
} finally {
    # email code
}

将电子邮件发送部分添加到
finally{}
块中。该块的要点是始终在其中运行代码,即使触发了
catch{}
块,即使发生了
catch
块未捕获的异常。

在注释后添加:

将现有代码包装到另一个
块中,然后将电子邮件代码放入该
块中:

try {
    import-Csv $intelSource -ErrorAction SilentlyContinue | ForEach-Object {
            $storageDir = "$($intelDir)\$($_.threatType) $($_.threatSubtype)"
            $threat = $_.threatType + "_" + $_.threatSubtype    # Set this variable to save headaches passing it later
            $storageFile = "$($storageDir)\$($threat)_$($(get-date -f MM-dd-yy)).csv"    # Filename specified by sources.csv fields and today's date
            $url = $_.threatLocation
            # Begin Error Logging
            try {
                $intelCount++
                $webclient.DownloadFile($url,$storageFile)
            }
            catch {
                $intelError++
                $intelErrorMessage = $_.Exception|format-list -force
                echo $intelErrorMessage | Out-File $intelDir\$threat"_ErrorLog_"$(get-date -f MM-dd-yy).txt -Append
                Continue
            }
            # End Error Logging
            # Cleanup
            finally {
                $webclient.Dispose()
            }
            # Throttling (mainly future use with multiple sources)
            Start-Sleep 5
            }
} finally {
    # email code
}


将电子邮件发送部分添加到
finally{}
块中。该块的要点是始终在那里运行代码,即使触发了
catch{}
块,即使发生了
catch
块未捕获的异常。

我尝试过,但随后我在sources.csv中为每个对象收到了1封电子邮件,该文件在本周末将有100多个对象。违背了摘要电子邮件的目的,产生了一堆垃圾邮件:/希望你还活着。虽然额外的try/catch保证发送电子邮件,但在遇到第一个错误后,原始的try/catch仍会停止处理对象(例如,如果sources.csv有5个对象,但第三个对象生成错误,则电子邮件会声明“3个中的1个”失败)@ayoungblood我承认,鉴于我正在查看的代码,我不知道会发生什么或为什么会发生这种情况。我强烈建议您在运行时仔细检查代码流和对象,看看为什么会发生这种情况。如果你不能通过这种方式找到它,它可能值得一个新的问题。目录不存在。我现在添加了一个带有
测试路径的
If
,和
mkdir
感叹这是一个接一个的脚本:P例如,现在我下载的站点只是重定向到它的主页,因为所有的脚本都无效queries@ayoungblood我不知道您使用的PowerShell版本是什么,但如果是3或更高版本,使用
调用WebRequest
而不是web客户端对象。您可以告诉它不要遵循重定向,然后测试响应以查看代码是什么。这将允许您抛出一个异常,并让您现有的catch处理它。当然,你也可以用.net对象来实现这一点,我只是不记得有多快。我尝试过这样做,但在sources.csv文件中,每个对象都会收到一封电子邮件。到本周末,这个文件将包含100多个对象。违背了摘要电子邮件的目的,产生了一堆垃圾邮件:/希望你还活着。虽然额外的try/catch保证发送电子邮件,但在遇到第一个错误后,原始的try/catch仍会停止处理对象(例如,如果sources.csv有5个对象,但第三个对象生成错误,则电子邮件会声明“3个中的1个”失败)@ayoungblood我承认,鉴于我正在查看的代码,我不知道会发生什么或为什么会发生这种情况。我强烈建议您在运行时仔细检查代码流和对象,看看为什么会发生这种情况。如果你不能通过这种方式找到它,它可能值得一个新的问题。目录不存在。我现在添加了一个带有
测试路径的
If
,和
mkdir
感叹这是一个接一个的脚本:P例如,现在我下载的站点只是重定向到它的主页,因为所有的脚本都无效queries@ayoungblood我不知道您使用的PowerShell版本是什么,但如果是3或更高版本,使用
调用WebRequest
而不是web客户端对象。您可以告诉它不要遵循重定向,然后测试响应以查看代码是什么。这将允许您抛出一个异常,并让您现有的catch处理它。当然,你也可以用.net对象来做这件事,我只是不记得有多随便。