locked
Send output to email RRS feed

  • Question

  • Hi,

    I built this PowerShell script to check on the installation of updates and server reboots, and ideally I would like to have it's output sent to email. I tried the send-mailmessage command, which does send an email, but in an unreadable format.
    Can you guys help me getting this right?

    This is the script so far:

    Set-ExecutionPolicy Bypass
    cd C:\PowerShellScripts\bin
    Import-Module .\ConfigurationManager.psd1
    
    $SiteServer = "oursiteserver"
    $SiteCode = "SSC"
    $CollectionName = "Collection"
    $Collection = get-wmiobject -ComputerName $siteServer -NameSpace "ROOT\SMS\site_$SiteCode" -Class SMS_Collection | where {$_.Name -eq "$CollectionName"}
    $Members = Get-WmiObject -ComputerName $SiteServer -Namespace  "ROOT\SMS\site_$SiteCode" -Query "SELECT * FROM SMS_FullCollectionMembership WHERE CollectionID='$($Collection.CollectionID)' order by name" | select Name 
    $Name = $Member.Name
    
    ForEach ($Member in $Members)
    {
    $body += '-'*50
    $body += 'Updates'
    $body += Write-Output "Eventlog from $Name for Windows Update information" 
    $body += Get-EventLog -computername $Name -LogName system -Newest 500 | Where-Object {$_.Message -notlike "*Definition*" -and $_.Eventid -ge "19" -and $_.Eventid -le "20"} | ft TimeGenerated, Message -AutoSize
    }
    
    ForEach ($Member in $Members)
    {
    $body += '-'*50
    $body += 'Reboots'
    $body += Write-Output "Eventlog from $name for Reboot" 
    $body += Get-EventLog -computername $Name -LogName system -Newest 500 | Where-Object {$_.Eventid -eq "1074"} | ft TimeGenerated, Message -AutoSize
    }
    
    $body = $body | Out-String
    
    $email = @{
    From = "system@test.com"
    To = "admin@test.com"
    Subject = "UpdateStatus"
    SMTPServer = "mail.test.com"
    Body = $body
    }
    
    send-mailmessage @email
    
    
    

    Tuesday, August 15, 2017 4:21 PM

Answers

  • define $body as an array before foreach

    $body = @()

    The body has to be a string.  It cannot bean array.  Also the output from Format-Table must be converted to a string before adding it to the body,  Format-Table outputs an array of table description objects.  It does not output text.

    Posting the code correctly formatted would be helpful.

    All commands that end with Format-Table must have "Out-String" added to the pipeline.


    \_(ツ)_/


    • Edited by jrv Tuesday, August 15, 2017 5:27 PM
    • Proposed as answer by Vincent Karunaidas Tuesday, August 15, 2017 5:36 PM
    • Marked as answer by Just_Tim Wednesday, August 30, 2017 8:07 AM
    Tuesday, August 15, 2017 5:26 PM

All replies

  • You must convert the table to a string.

    $body = $body | Out-String


    \_(ツ)_/

    Tuesday, August 15, 2017 4:37 PM
  • It's in my code, but maybe in the wrong location?
    Tuesday, August 15, 2017 4:41 PM
  • Its not in the code you posted.


    \_(ツ)_/

    Tuesday, August 15, 2017 4:46 PM
  • define $body as an array before foreach

    $body = @()

    Tuesday, August 15, 2017 5:15 PM
  • define $body as an array before foreach

    $body = @()

    The body has to be a string.  It cannot bean array.  Also the output from Format-Table must be converted to a string before adding it to the body,  Format-Table outputs an array of table description objects.  It does not output text.

    Posting the code correctly formatted would be helpful.

    All commands that end with Format-Table must have "Out-String" added to the pipeline.


    \_(ツ)_/


    • Edited by jrv Tuesday, August 15, 2017 5:27 PM
    • Proposed as answer by Vincent Karunaidas Tuesday, August 15, 2017 5:36 PM
    • Marked as answer by Just_Tim Wednesday, August 30, 2017 8:07 AM
    Tuesday, August 15, 2017 5:26 PM
  • Line 28...
    Tuesday, August 15, 2017 5:29 PM
  • Line 28...

    Sorry - I am blind today.

    Fix the format statements.


    \_(ツ)_/

    Tuesday, August 15, 2017 5:31 PM
  • Looking at your code there are many design issues and other errors that will prevent this from working.

    Here is part of what you are trying to do.  The code in the loop does not make any sense.  Where does $name come from.

    $body += ('-' * 50) + "`n"
    $body += "Update`n"
    $body += "Eventlog from $Name for Windows Update information`n"
    $events = ForEach ($Member in $Members) {
    	Get-WinEvent -computername $Name -FilterHashtable @{ LogName='system'; ID = 19,20 } -MaxEvents 500 
    }
    $body += $events | 
    	Format-Table MachineName,TimeCreated, Message -AutoSize |
    	Out-String
    

    I recommend that you start by rethinking this one piece at a time.  Test each piece at a prompt until you understand what is happening.


    \_(ツ)_/

    Tuesday, August 15, 2017 5:46 PM
  • Ok.

    This should be:

    $events = ForEach ($Member in $Members) {
           Get-WinEvent -computername $Member.Name -FilterHashtable @{ LogName='system'; ID = 19,20 } -MaxEvents 500
    }


    \_(ツ)_/

    Tuesday, August 15, 2017 5:50 PM
  • This can also be stated more simply:

    $events Get-WinEvent -computername ($members.Name) -FilterHashtable @{ LogName='system';ID = 19,20 } -MaxEvents 500

    You would also do better by setting "StartTime" and "EndTime" for  specific range rather than setting maxevents.

    help Get-WinEvent -full

    We don't use Get-EventLog anymore as it does not work well with the Vista and later event logs.  Get-Evenlog was for W2k3 and earlier system.


    \_(ツ)_/


    • Edited by jrv Tuesday, August 15, 2017 5:54 PM
    Tuesday, August 15, 2017 5:54 PM
  • Thanks for your input.
    I changed the code a bit, with much better results, I now have a readable email!
    Will look into the get-winevent command tomorrow.

    I might also look into changing the output to HTML before emailing it, instead of using $body.
    Do you have any advise on the easiest way to accomplish this?

    Set-ExecutionPolicy Bypass
    cd C:\PowerShellScripts\bin
    Import-Module .\ConfigurationManager.psd1
    
    $SiteServer = "server"
    $SiteCode = "AAA"
    $CollectionName = "Collection"
    $Collection = get-wmiobject -ComputerName $siteServer -NameSpace "ROOT\SMS\site_$SiteCode" -Class SMS_Collection | where {$_.Name -eq "$CollectionName"}
    $Members = Get-WmiObject -ComputerName $SiteServer -Namespace  "ROOT\SMS\site_$SiteCode" -Query "SELECT * FROM SMS_FullCollectionMembership WHERE CollectionID='$($Collection.CollectionID)' order by name" | select Name 
    $body = $body | Out-String
    
    ForEach ($Member in $Members)
    {
    $Name = $Member.Name
    $body += Write-Output "$Name Update info" 
    $body += Get-EventLog -computername $Name -LogName system -Newest 500 | Where-Object {$_.Message -notlike "*Definition*" -and $_.Eventid -ge "19" -and $_.Eventid -le "20"} | ft TimeGenerated, Message -AutoSize | Out-String
    $body += Write-Output "$Name Reboot info" 
    $body += Get-EventLog -computername $Name -LogName system -Newest 500 | Where-Object {$_.Eventid -eq "1074"} | ft TimeGenerated, Message -AutoSize | Out-String
    }
    
    $email = @{
    From = "Server@test.com"
    To = "User@test.com"
    Subject = "Status"
    SMTPServer = "mail.test.com"
    Body = $body
    }
    
    send-mailmessage @email
    

    Tuesday, August 15, 2017 7:51 PM
  • We do not need to use Write-Output to assign strings.

    Here are some examples and discussions of how to do multiple tables with HTML.  It is a three part blog post.

    http://tech-comments.blogspot.com/2012/07/powershell-dynamically-color-posh.html


    \_(ツ)_/

    Tuesday, August 15, 2017 8:56 PM