Search code examples
powershellget-winevent

Powershell - Get-WinEvent - send email with message from Event


I am new in powershell. I want to get the events from Task Scheduler/Operational with code of failure, and send an email with all events in the body.

# Get all events from yesterday with ID=103 and Text, put in table and send email
   
# Get the event entries.
$eventEntries = & {Get-WinEvent  -FilterHashtable @{ LogName='Microsoft-Windows-TaskScheduler/Operational'; StartTime=(Get-Date).AddDays(-1); ID='103'} | 
    Where {$_.Message.Contains('Task Scheduler failed to start instance')} | 
    select -Property ID,TimeCreated,Message |ft -wrap}
            
# Create a table row for each entry.
$array = @()

foreach ($eventEntry in $eventEntries)
{
     $array += $eventEntry
}
$array | Format-table

# Create the email.
$MailFrom = "[email protected]"
$MailTo = "[email protected]"
$Subject = "EventLogAlert"
$email = New-Object System.Net.Mail.MailMessage( $MailFrom , $MailTo )
$email.Subject = $Subject
$email.IsBodyHtml = $true
$email.Body = @"
<table style="width:100%;border">
     <tr>
         <th style="text-align: center; padding: 5px;">ID</th>
         <th style="text-align: center; padding: 5px;">TimeCreated</th>
         <th style="text-align: center; padding: 5px;">Message</th>
        </tr>
    
    $array
    </table>
"@

# Send the email.
$SmtpServer = "smtp.mail.outlook.com"
$SmtpPort = 587
$SmtpUser = "[email protected]"
$SmtpPassword = "passwordexample"
$SMTPClient=New-Object System.Net.Mail.SmtpClient($SmtpServer,$SmtpPort)
$SMTPClient.EnableSsl=$true
$SMTPClient.Credentials= New-Object System.Net.NetworkCredential($SmtpUser,$SmtpPassword);
$SMTPClient.Send($email)

The $array is created with values in it, can viewed with echo $eventEntries The result $email is not with values from table, it give this text

Microsoft.PowerShell.Commands.Internal.Format.FormatStartData Microsoft.PowerShell.Commands.Internal.Format.GroupStartData Microsoft.Powershell.Commands.Internal.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.GroupEndData Microsoft.PowerShell.Commands.Internal.Format.FormatEndData 

Can somebody help me to write correct code to view all events in email.

And additionally, to create for each event an email separately.

Thanks in advance!


Solution

  • You should not use Format-Table if you plan on using the data any further, because that cmdlet is only meant for display purposes.

    Try the code below:

    $yesterday = (Get-Date).AddDays(-1).Date   # set to midnight
    $filter    = @{LogName='Microsoft-Windows-TaskScheduler/Operational'; StartTime=$yesterday; ID='103'}
    $events    = Get-WinEvent -FilterHashtable $filter -ErrorAction SilentlyContinue | 
                 Where-Object {$_.Message -like '*Task Scheduler failed to start instance*'} | 
                 Select-Object -Property TaskDisplayName,ID,TimeCreated,Message
    
    $style = @'
    <style>
        body {font-family: Calibri, Tahoma, Helvetica, sans-serif; color: black;}
        table {width: 100%; border-width: 1px; border-style: solid; border-color: black; border-collapse: collapse;}
        th {text-align: center; padding: 5px; background-color: #6495ED; color: white;}
        td {border-width: 1px; padding: 3px; border-style: solid; border-color: black;}
    </style>
    '@
    
    # to use for both the email as the subject for this email
    $subject = 'EventLogAlert {0:yyyy-MM-dd HH:mm:ss}' -f (Get-Date)
    
    # create the email body using the style above for the table
    $body = $events | ConvertTo-Html -Head $style -PreContent "<h2>$subject</h2>"
    
    # Create the email.
    $MailFrom = "[email protected]"
    $MailTo   = "[email protected]"
    $email    = New-Object System.Net.Mail.MailMessage($MailFrom, $MailTo)
    $email.Subject    = $subject
    $email.IsBodyHtml = $true
    $email.Body       = $body -join [environment]::NewLine
    
    # Send the email.
    $SmtpServer   = "smtp.mail.outlook.com"
    $SmtpPort     = 587
    $SmtpUser     = "[email protected]"
    $SmtpPassword = "passwordexample"
    $SMTPClient   = New-Object System.Net.Mail.SmtpClient($SmtpServer, $SmtpPort)
    $SMTPClient.EnableSsl   = $true
    $SMTPClient.Credentials = New-Object System.Net.NetworkCredential($SmtpUser, $SmtpPassword);
    $SMTPClient.Send($email)
    

    Notes:

    • I'm using the -like operator rather than the .Contains() string method, because the latter is case-sensitive
    • I have set yesterda's date to midnight by appending .Date
    • The styling is all up to you, this is just an example you may or may not like..