0

自動化された Powershell Hyper-V バックアップ スクリプトに少し問題があります。スクリプトは完全に機能しますが、私の問題は、ログ ファイルを添付して電子メールを送信しようとすると、送信に失敗した後にファイルのロックが解除されないことです。(メールの送信に成功した場合の動作を確認することはできませんが、正直なところ、送信に失敗した場合でも破棄する必要があります。)

私はウェブ全体を検索しましたが、見つけることができたのは次のいずれかです。

  1. Send-MailMessage は、メールの送信後に添付ファイルを自動的に破棄します。
  2. new-object system.net.mail.mailmessage と new-object system.net.mail.attachment で Powershell v1 のメソッドを使用します。

私のコードの一部を次に示します (必要なコードの要点のみに短縮しました)。

[String]$ComputerName = Get-Content Env:ComputerName
[String]$LogFile = "Hyper-V Backup Logs\$ComputerName.Hyper-V Backup." + (Get-Date).Day + "-" +(Get-Date).Month + "-" +(Get-Date).Year + "-" +(Get-Date).Hour + "." +(Get-Date).Minute + "." +(Get-Date).Second + ".log"

"# $(Get-Date) :: Attempting to send log file to 'Support@example.dk'..." | Out-File $LogFile -Append
Try
{
    $EmailTo = "Support@example.dk"
    $EmailFrom = "Service@example.dk"
    $EmailServer = "server.example.dk"
    $EmailSubject = "An error occurred during Hyper-V Backup on $ComputerName!"
    $EmailBody = "Hello,

    An error occured during Hyper-V Backup on $ComputerName.

    I have attached the log file, $LogFile, to this mail.

    Kind Regards,<br></p>
    Hyper-V Backup.
    "

    Send-MailMessage -From $EmailFrom -To $EmailTo -Subject $EmailSubject -Body $EmailBody -Attachments $LogFile -SmtpServer $EmailServer
    "# $(Get-Date) :: Successfully send log file to 'Support@example.dk" | Out-File $LogFile -Append

}
Catch
{
    "# $(Get-Date) :: Failed to send log file to 'Support@example.dk" | Out-File $LogFile -Append
    "                      :: Error Command: Send-MailMessage -From $EmailFrom -To $EmailTo -Subject $EmailSubject -Body $EmailBody -Attachments $LogFile -SmtpServer $EmailServer" | Out-File $LogFile -Append
    "                      :: Error Message: $($_.Exception.Message)" | Out-File $LogFile -Append
}

次のエラーがスローされます。

Out-File : The process cannot access the file 'C:\Hyper-V Backup\Hyper-V Backup
Logs\example.Hyper-V Backup.22-8-2013-13.48.16.log' because it is being used by
another process.
At C:\Hyper-V Backup\Hyper-V Backup.ps1:310 char:163
+ ... port@example.dk" | Out-File $LogFile -Append
+                    ~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OpenError: (:) [Out-File], IOException
    + FullyQualifiedErrorId : FileOpenFailure,Microsoft.PowerShell.Commands.OutFileCommand

私の質問は、電子メールの送信に失敗した後、Send-MailMessage で添付ファイルを破棄して、スクリプトがログ ファイルへの書き込みを続行できるようにするにはどうすればよいかということです。

PS。上記のスクリプトは、メールが正常に送信されたときに、エラーをスローしたり、ファイルをロックしたりすることなく機能します。

敬具、

トーマス・シュミット

編集:

代わりに、古い Powershell v1 の方法を使用しました。

Try
{
    $SMTPServer = "exchange.example.dk"
    $SMTP = new-object Net.Mail.SmtpClient($SMTPServer)

    $EmailAttachment = new-object Net.Mail.Attachment($Logfile)
    $EmailMessage = new-object Net.Mail.MailMessage

    $EmailMessage.Attachments.Add($EmailAttachment)
    $EmailMessage.From = "service@example.dk"
    $EmailMessage.To.Add("spport@example.dk")
    $EmailMessage.Subject = "Notification from email server"
    $EmailMessage.Body = "Hello,
An error occurred during A/S Hyper-V Backup on $ComputerName.

I have attached the log file, $LogFile, to this mail.

Kind Regards,
Hyper-V Backup.
"
    $SMTP.Send($EmailMessage)
    $EmailAttachment.Dispose()
    Write-Host "# $(Get-Date) :: Successfully send log file to 'Support@example.dk" -foregroundcolor green; "# $(Get-Date) :: Successfully send log file to 'Support@example.dk" | Out-File $LogFile -Append
}
Catch
{
    $EmailAttachment.Dispose()
    Write-Host "# $(Get-Date) :: Failed to send log file to 'Support@example.dk" -foregroundcolor red; "# $(Get-Date) :: Failed to send log file to 'Support@example.dk" | Out-File $LogFile -Append
    "                      :: Error Command: SMTP.Send(EmailMessage)" | Out-File $LogFile -Append
    "                      :: Error Message: $($_.Exception.Message)" | Out-File $LogFile -Append
}

しかし、誰かが上記の答えを提供できる場合は、代わりにその解決策を使用したいと思います!

敬具、

トーマス・シュミット

4

2 に答える 2

1

これは私がそれを処理した方法であり、私にとってはうまくいっているようです:

 try {
    $ErrorActionPreference = 'Stop'
    $SmtpSettings = @{
        To = $Recipients.Split(',')
        From = $Sender
        SmtpServer = $SmtpServer
        Subject = "Email test"
        Body = "Please check attached file"
        Attachment = $Attachment
    }
    Send-MailMessage @SmtpSettings -BodyAsHtml
 } catch {
    $ErrorActionPreference = 'Continue'
    [gc]::collect()
    $CustomError = ($_ -replace "`r`n","")
    $ScriptLine = "$($_.InvocationInfo.ScriptLineNumber)" +','+ "$($_.InvocationInfo.OffsetInLine)"
    Write-Verbose "Error sending email: $CustomError (script line $ScriptLine)"
}

私は基本的にガベージコレクター - [gc]::collect()を使用しており、電子メールの送信中にエラーが発生したにもかかわらず、添付ファイルのロックを解除しました。また、tryで$ErrorActionPreference = 'Stop'を設定して、エラーを適切にキャッチし、catch内で$ErrorActionPreference = 'Continue'を設定して、スクリプトが完全に停止しないようにしました。

于 2015-11-01T20:07:18.757 に答える