none
Sending the output of a PowerShell script via email

    Question

  • Hi everyone, there's a few threads here around this topic but I'm still having problems getting my head around having PowerShell send an email. The Send-MailMessage command makes sense, but getting the output of a script I run to check DFS backlog, sent in the message of the email is where I'm stuck.

    The script I manually run a few times a day to check DFS backlog is;

    SCRIPT WIP REMOVED - WORKING ONE APPENDED TO THREAD

    Write-host "XXX" refers to the Replicated Folders name. Everything else should no doubt make sense to anyone familiar with dfsrdiag backlog etc

    What I want to do is setup a scheduled task to run this 2-3 times a day, which isn't a problem, but how can I have the output of the script emailed?

    All advice appreciated :)

    Cheers Shane.


    • Edited by Shane Bryan Friday, February 10, 2012 3:29 AM
    Thursday, February 9, 2012 11:20 PM

Answers

  • Go back and read the posts a little closer.  You need to get your output collected into a variable.  Right now, your just spitting it out to, well basically nowhere (in a scheduled task because there's no console to display it on).

    Once you have it in that variable then you  still have it when it's time to send your email. 

    As far as sending the email goes, send-mailmessage is much easier than the system.net.mail method.  The command line can get a bit long with all the required parameters, but there's something called "splatting" you can do that will let you put those parameters and values into a hash table so they're easier to look at and keep organized.  The equivalent of your code, using a hash table and send-mailmessage would look like this:

    $email = @{
    From = "shane.bryan@msaustralia.org.au"
    To = "shane.bryan@msaustralia.org.au"
    Subject = "Powershell Test"
    SMTPServer = "rc-ex01.msl.local"
    Body = $body
    }
    
    send-mailmessage @email


    [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "

    • Marked as answer by Shane Bryan Friday, February 10, 2012 1:18 AM
    Friday, February 10, 2012 12:39 AM

All replies

  • Write-Host simply returns output to the Console host...nothing else.  It is strongly recommended that, if you are going to output to host (and something else) use Write-Output.  In my scripts like this I create a variable and use the += operator to add the new text to the variable.  When I am done I just specify the variable as the Body parameter in the Send-MailMessage cmdlet.  I cannot tell if you have looked at this one yet from the oroginal post, so, here is the help on it.  It's standard in v2:

    Send-MailMessage -?
    
    NAME
        Send-MailMessage
    
    SYNOPSIS
        Sends an e-mail message.
    
    
    SYNTAX
        Send-MailMessage [-To] <string[]> [-Subject] <string> -From <string> [[-Body] <string>] [[-SmtpServer] <string>] [-
        Attachments <string[]>] [-Bcc <string[]>] [-BodyAsHtml] [-Cc <string[]>] [-Credential <PSCredential>] [-DeliveryNot
        ificationOption {None | OnSuccess | OnFailure | Delay | Never}] [-Encoding <Encoding>] [-Priority {Normal | Low | H
        igh}] [-UseSsl] [<CommonParameters>]
    
    
    DESCRIPTION
        The Send-MailMessage cmdlet sends an e-mail message from within Windows PowerShell.
    
    
    RELATED LINKS
        Online version: http://go.microsoft.com/fwlink/?LinkID=135256
    
    REMARKS
        To see the examples, type: "get-help Send-MailMessage -examples".
        For more information, type: "get-help Send-MailMessage -detailed".
        For technical information, type: "get-help Send-MailMessage -full".

    Friday, February 10, 2012 12:09 AM
  • I think you only need to do the following:

    1. get the output of your script into a variable
    2. supply that variable as the -body parameter to the send-mailmessage cmdlet

    The trouble is your write-host outputcannot be redirected or pipelined. Try changing that to write-output.

    If dfsrdiag does its output to stdout, that should be ok.

    Once you have your script changed so its output can be redirected, you could call it something like this:

    $body = <path to your script>.ps1
    send-mailmessage -body $body ... etc.
    

    If you really need the emailed copy to have the same colour characteristics as your above script produces, you could do this by including appropriate html tags in the output of your script and add the -bodyAsHtml parameter to the send-mailmessage call.
    Friday, February 10, 2012 12:10 AM
  • First, don't use "write-host" as your output in a script that's going to run as a scheduled task.  Nobody is going to be there to read it.

    I usually start with an empty array for the body:

    $body = @()

    Then every line you want to have in your email, add to that array:

    $body += 'Group Share'

    $body += dfsrdiag Backlog /ReceivingMember:bb-file01 /SendingMember:rc-file01 /RGName:"MSL-DFS" /RFName:"GroupShare"

    body += '='*50

    lather, rinse, repeat.

    before you send the email, do this:

    $body = $body | out-string

    That will turn it into as string (which is what send-mailmessage is expecting), and add newlines.

     But that's just how I do it.    There's lots of ways you could do it, and somebody else may have other ideas you like better.


    [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "



    • Edited by mjolinor Friday, February 10, 2012 12:57 AM
    Friday, February 10, 2012 12:20 AM
  • thanks :) yep I realise what 'write-host' does, and that the new script will not need that.

    here's what I have so far, 

    SCRIPT WIP REMOVED - WORKING ONE APPENDED TO THREAD

    But, I think I need to create a string for every DFS folder, as all it's currently doing is sending the result of the first $scr, not the rest.

    Please excuse the noob in the room :)

    ideally, in each line where it reports the backlog, it would also indicate which DFS folder it's referring to.


    -my Karma ran over your Dogma



    • Edited by Shane Bryan Friday, February 10, 2012 3:29 AM
    Friday, February 10, 2012 12:24 AM
  • I think it is the result of the last dfsrdiag run being sent, not the first.

    Regardless, as Rob suggested initialize your output accumulator variable as an empty array:

        $scr=@()

    and then instead of:

        $scr = whatever

    do this:

        $scr += whatever

    Friday, February 10, 2012 12:38 AM
  • Go back and read the posts a little closer.  You need to get your output collected into a variable.  Right now, your just spitting it out to, well basically nowhere (in a scheduled task because there's no console to display it on).

    Once you have it in that variable then you  still have it when it's time to send your email. 

    As far as sending the email goes, send-mailmessage is much easier than the system.net.mail method.  The command line can get a bit long with all the required parameters, but there's something called "splatting" you can do that will let you put those parameters and values into a hash table so they're easier to look at and keep organized.  The equivalent of your code, using a hash table and send-mailmessage would look like this:

    $email = @{
    From = "shane.bryan@msaustralia.org.au"
    To = "shane.bryan@msaustralia.org.au"
    Subject = "Powershell Test"
    SMTPServer = "rc-ex01.msl.local"
    Body = $body
    }
    
    send-mailmessage @email


    [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "

    • Marked as answer by Shane Bryan Friday, February 10, 2012 1:18 AM
    Friday, February 10, 2012 12:39 AM
  • I've got it, thanks mjolinor :)

    this is working so far...

    SCRIPT WIP REMOVED - WORKING ONE APPENDED TO THREAD


    will finish it off and schedule it up!


    -my Karma ran over your Dogma


    • Edited by Shane Bryan Friday, February 10, 2012 3:29 AM
    Friday, February 10, 2012 12:44 AM
  • Ignore that part about the output going nowhere in my last post.  I missed that you were sending it to $scr.  The problem with that method is that you're overwriting $scr every time.  That's why you end up with just one line.

    You can use += to add each line, but you need to do that into an array to keep the llines separated.  If you don't use an array, the first time you do $scr += <some command> the output of that command will be in $scr, but it will be a string.  Then when you do that next one, that string will get appended onto the first one, and when your done, you have one really long line.


    [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "

    Friday, February 10, 2012 12:51 AM
  • thanks, it's working great. I changed it to use send-mailmessage  based on your advice also :)

    -my Karma ran over your Dogma

    Friday, February 10, 2012 1:21 AM
  • For the record, here's the final script. thanks again everyone!

    # This script checks the MSL-DFS replication group for any files that may be backloged and sends the results via email.

    $body = @()
    $body += 'Group Share'
    $body += dfsrdiag Backlog /ReceivingMember:bb-file01 /SendingMember:rc-file01 /RGName:"MSL-DFS" /RFName:"GroupShare"

    $body += '-'*50
    $body += 'Home Shares'
    $body += dfsrdiag Backlog /ReceivingMember:bb-file01 /SendingMember:rc-file01 /RGName:"MSL-DFS" /RFName:"HomeShares"

    $body += '-'*50
    $body += 'Archived Home Shares'
    $body += dfsrdiag Backlog /ReceivingMember:bb-file01 /SendingMember:rc-file01 /RGName:"MSL-DFS" /RFName:"Archived Homeshares"

    $body += '-'*50
    $body += 'RC-SQL01'
    $body += dfsrdiag Backlog /ReceivingMember:bb-file01 /SendingMember:rc-file01 /RGName:"MSL-DFS" /RFName:"RC-SQL01"

    $body += '-'*50
    $body += 'RC-SQL02'
    $body += dfsrdiag Backlog /ReceivingMember:bb-file01 /SendingMember:rc-file01 /RGName:"MSL-DFS" /RFName:"RC-SQL02"

    $body += '-'*50
    $body += 'RC-SQL03'
    $body += dfsrdiag Backlog /ReceivingMember:bb-file01 /SendingMember:rc-file01 /RGName:"MSL-DFS" /RFName:"RC-SQL03"

    $body += '-'*50
    $body += 'Oracle'
    $body += dfsrdiag Backlog /ReceivingMember:bb-file01 /SendingMember:rc-file01 /RGName:"MSL-DFS" /RFName:"Oracle"

    $body = $body | out-string

    $email = @{
    From = "Network_Alerts@EMAIL.COM"
    To =
    "EMAIL@EMAIL.COM"
    CC = "EMAIL@EMAIL.COM"
    Subject = "DFS Replication Backlog Status"
    SMTPServer = "SERVERNAME"
    Body = $body
    }

    send-mailmessage @email

    A nicely formatted email now arrives in the Sys Admin mailbox a few times a day :)


    -my Karma ran over your Dogma




    • Edited by Shane Bryan Friday, February 10, 2012 3:32 AM
    Friday, February 10, 2012 3:26 AM