Send email alert from Performance Monitor using PowerShell script
Asked Answered
G

1

5

I have created an alert in Performance Monitor (Windows Server 2008 R2) that should be triggered whenever \Processor(_Total)\% Processor Time is Above 10 (a small value just to guarantee that the condition for sending the alert is always met). You can see the Alert Task properties in the image.

enter image description here

In addition, I have also created a new task in the Task Scheduler that will run whether the user is logged on or not, and it will run with highest privileges. The trigger for this task has the following properties:

  • Begin the task: On an event
  • Settings: Basic
  • Log: System
  • Source: Processor

The Actions (and this is the part I don't know if it's correct) has the following settings:

  • Action: Start a program
  • Program/script: the path to a PowerShell script to send an email.

The PowerShell code is the following ($name, $date, $counter, $threshold, $value are supposed to come from the Performance Monitor data collector set alert task properties, as in the image above):

function SendMail ($name, $date, $counter, $threshold, $value) {
  $MailMessage = New-Object Net.Mail.MailMessage
  $MailMessage.To.Add("[email protected]")
  $MailMessage.From = "[email protected]"
  $MailMessage.Subject = "ALERT - Performance Monitor"
  $MailMessage.IsBodyHtml = $True

  $MailMessage.Body = @"
    <html><head></head><body>
    The following counter needs attention:<BR><BR>
    Name: $($name)<BR>
    Date: $($date)<BR>
    Counter: $($counter)<BR>
    Threshold: $($threshold)<BR>
    Actual Value: $($value)<BR>
    <FONT face=Courier>$($html)</FONT>
    <BR>
    --- Automatically generated with SENDMAIL function ---
    </body>
    </html>
"@

  $SmtpClient = New-Object Net.Mail.SmtpClient("blah.bleh")
  $SmtpClient.Send($MailMessage)
}

Once the task is started, I have the following in the History: Task Started, Action Started, and Created ask Process. The email is never sent though.

I tried sending an email using the Action: Send an email, and it worked fine. Does anyone know what could be wrong?

Gook answered 27/8, 2013 at 21:8 Comment(6)
Are you sure all parameters are getting passed correctly in the script. Another thing is if you are using powershell v3 then you can use send-mailmessage cmdlet -https://mcmap.net/q/2033464/-powershell-script-to-monitoring-status-and-send-email-resultsCarley
@Mitul: Do you mean the parameters $name, $date, etc? If so, how can I check? If you are referring to the parameter like email, smtp server, etc, I'm using the same as I used in the Action: Send an email (with the difference that, in the script, my smtp server starts with "SMTP." (And unfortunately, I'm not using v3 :(Gook
The code you posted defines a function, but I don't see you calling that function anywhere.Bland
To test it comment out everything and output values to a text file.Carley
@Carley PSv2 has Send-MailMessage.Sueannsuede
@Ansgar Wiechers: How do I call the function passing the task arguments? (Sorry, I never used PowerShell or the Task Scheduler before)Gook
G
8

There are basically two things to address that should make this work for you.

  1. Get the alert parameters correctly passed to your script.
  2. Actually call the function defined in your script.

We'll start with the parameters. On the Alert Task tab of your alert (pictured above), edit the Task Arguments field and replace:

{name}{date}{counter}{threshold}{value}

with:

"{name}" "{date}" "{counter}" "{threshold}" "{value}"

Your parameters are basically being parsed as a space-separated string value, so we add double-quotes around each individual parameter token to handle values that include spaces, and we add a space between each individual parameter token so that we'll be able to tell one parameter from the next.

Then, for the action of your scheduled task (named "Processor Monitoring") you have to tell it to expect parameters from the alert and to pass those parameters to the PowerShell script.

enter image description here

Your Action is correct, i.e. "Start a program".

For the Program/script field, enter "powershell.exe" (or browse for the full path).

And for the Add Arguments field, enter this:

-File C:\path\to\your\PowerShell\scripts\perfmon_send_email.ps1 $(Arg0)

Where perfmon_send_email.ps1 is the script file containing your SendMail() function as described above.

This bit was kind of finicky, so there may be other ways to set this up, but explicitly using the -File parameter made a difference for my tests. The $(Arg0) part is what gets replaced with the parameter string from the Alert when the scheduled task executes PowerShell to run your script.

So that should make the Alert parameters available to your PowerShell script. Now all you have to do is actually call the function you've already defined. Add the following to the end of your script (after the function definition):

# Get parameter values by position and pass them to the SendMail() function.
SendMail $args[0] $args[1] $args[2] $args[3] $args[4]

$args is an array containing the parameter values passed to a script file called from the command line, which is exactly what we configured the scheduled task to do.

Since we know the alert will always send the same values in the same order, i.e. name, date, counter, threshold, and value, we can just pull them from the command line arguments based on position and pass them to the SendMail() function.

Note that there are more robust ways to process command line arguments, but this should be sufficient for your purposes.

Gusta answered 28/8, 2013 at 23:19 Comment(6)
Wow! Thank you @Gusta so much for the detailed explanation!! I really appreciate it! However, I cannot test if it works because I'm having the following error msg when running my script: Exception calling "Send" with "1" argument(s): "Failure sending mail." (for the line $SmtpClient.Send($MailMessage)). What is causing this and how do I fix it?Gook
Never mind! The problem was that I set my smtp client to be "SMTP.blah.bleh", when it actually just needs to be "blah.bleh" :)Gook
So I finally got the script to send email properly (YAY!!!). But the parameters are not being passed in the email. So this is the body of the email: <html><head></head><body>=0D=0AThe following counter needs attention:<BR><BR>==0D=0AName: $(Arg0)<BR>=0D=0ADate: <BR>=0D=0ACounter: <BR>=0D=0AThreshold:=<BR>=0D=0AActual Value: <BR>=0D=0A<FONT face=3DCourier></FONT>=0D=0A=0D=0A<BR>==0D=0A--- Automatically generated with SENDMAIL function ---=0D=0A = </body>=0D=0A </html>. The counter should be "% Processor Time", Threshold should be 10, and actual value should be around 50. Any thoughts?Gook
What I found is that the email is only send once I start the task, not when it detects that the performance counter is above the limit (so that's why none of the values are displayed in the email). Initially, I had my task in the task scheduler set to be triggered "On an event", with the Log being System and the Source being Processor and off course it didn't work. Then I changed Log to Application and Source to PrefCtrs, but still the counter is only triggered when I start the task. What could be wrong?Gook
I don't know if the Log and Source values make a difference, or not. I'm pretty sure it's just looking at the name; maybe make sure your task name exactly matches the value specified on the "alert task" tab of the alert, i.e. "Processor Monitoring" in your screen cap above.Gusta
I'm not sure if this was the solution, by I changed the task name to ProcessorMonitoring (no spaces) and it works. It sends an email everytime a record is registered in the logs (that is, even when there is no data for the data collectors), but I handled it in the script (if argument is not empty, send email). Thank you @Gusta for your help :)Gook

© 2022 - 2024 — McMap. All rights reserved.