Programming Windows Services with Microsoft Visual Basic 2008 : Service Notification

2/18/2013 6:23:04 PM

Although putting an entry in the Application log may suffice, you might be required at times to also send a notification when a problem is found and a process has been terminated. In this last section we will implement the code necessary to send an e-mail alert when a process is terminated.

Updating the Configuration.xml File

Listing 1 represents the changes required to our configuration file so that the code will send an administrative alert.

Listing 1. E-mail configuration elements.
<Subject>Test Subject</Subject>
<Message>Found Message</Message>

Updating the WMI Class

We have to update the WMI class to enable e-mail notifications. We will add the code shown in Listing 2 to our WMI class to reflect these changes. You can add them to any section of your WMI class.

Listing 2. WMI e-mail notification changes.
Private m_SmtpClient As New SMTP
Private m_MailEnabled As Boolean
Public Property MailEnabled() As Boolean
      Return m_MailEnabled
  End Get
  Set(ByVal value As Boolean)
      m_MailEnabled = value
  End Set
End Property

Public ReadOnly Property SmtpClient() As SMTP
      Return m_SmtpClient
  End Get
End Property

As with the FileWorker class, these properties will be used to implement e-mail notifications in the WMI class.

Updating the WMIWorkerOptions Class

Now that we have the WMI changes made, we need to update the WMIWorkerOptions class to store the properties required to send the e-mail notification. Listing 3 shows the required changes. You will also notice that we need to update the <Copy> method to reflect these additional properties.

Listing 3. WMIWorkerOptions e-mail notification property changes.
Private m_MailDetail As New EmailDetail

Public Property EmailProperties() As EmailDetail
        Return m_MailDetail
    End Get
    Set(ByVal value As EmailDetail)
        m_MailDetail = EmailDetail.Copy(value)
    End Set
End Property

Public Shared Sub Copy(ByVal wwo1 As WMIWorkerOptions, _
                 ByVal wwo2 As WMIWorkerOptions)
    wwo1.Query = wwo2.Query
    wwo1.Server = wwo2.Server
    wwo1.WMIRoot = wwo2.WMIRoot
    wwo1.EmailProperties.Message = wwo2.EmailProperties.Message
    wwo1.EmailProperties.Recipient = wwo2.EmailProperties.Recipient
    wwo1.EmailProperties.Sender = wwo2.EmailProperties.Sender
    wwo1.EmailProperties.SmtpPort = wwo2.EmailProperties.SmtpPort
    wwo1.EmailProperties.SmtpServer = wwo2.EmailProperties.SmtpServer
    wwo1.EmailProperties.Subject = wwo2.EmailProperties.Subject
End Sub

The changes shown in Listing 3 reflect not only the implementation of the e-mail properties, but also the initialization of the e-mail properties in our <Copy> method.

Updating the <Tutorials.ThreadFunc> Method

Now that we have our new configuration elements and a place to store the properties in the WMIWorkerOptions class, we need to implement the changes required to read and assign these values. This will happen in our <ThreadFunc> method, as shown in Listing 4.

Listing 4. <ThreadFunc> e-mail notification changes.
If (Not tmpOptions Is Nothing) Then
  Dim WWOptions As New WMIWorkerOptions
  Dim children As System.Xml.XPath.XPathNavigator
          children = tmpOptions.SelectSingleNode("Query")
          WWOptions.Query = children.Value

          children = tmpOptions.SelectSingleNode("Server")
          WWOptions.Server = children.Value

          children = tmpOptions.SelectSingleNode("WMIRoot")
          WWOptions.WMIRoot = children.Value

          children = tmpOptions.SelectSingleNode("Process")
          WWOptions.Process = children.Value

  Dim tmpDetail As New EmailDetail
children = tmpOptions.SelectSingleNode("Message")
							tmpDetail.Message = children.Value
							children = tmpOptions.SelectSingleNode("Subject")
							tmpDetail.Subject = children.Value
							children = tmpOptions.SelectSingleNode("Sender")
							tmpDetail.Sender = children.Value
							children = tmpOptions.SelectSingleNode("Recipient")
							tmpDetail.Recipient = children.Value
							children = tmpOptions.SelectSingleNode("SmtpPort")
							tmpDetail.SmtpPort = children.Value
							children = tmpOptions.SelectSingleNode("SmtpServer")
							tmpDetail.SmtpServer = children.Value
							WWOptions.EmailProperties = tmpDetail
							Dim tmpWW As New WMI(m_ThreadAction, WWOptions)
							children = tmpOptions.SelectSingleNode("MailEnabled")
							tmpWW.MailEnabled = Convert.ToBoolean(children.Value)
      Catch ex As Exception
          WriteLogEvent(ex.ToString(), CONFIG_READ_ERROR,
            EventLogEntryType.Error, My.Resources.Source)
      End Try
  Loop While (tmpOptions.MoveToNext)
  End If
End If


The code in Listing 8-19 reads the values of our e-mail properties from the configuration file and then populates the EmailDetail property of our WMIWorkerOptions class instance for each monitored process. Then it enables or disables e-mail notifications based on the Mail-Enabled element in our configuration file.

Updating the <WMI.ProcessWMIRequest> Method

Now we need to update the worker thread to send the e-mail notification when we terminate a process. Listing 5 shows these updates.

Listing 5. <ProcessWMIRequest> e-mail notification code.
'terminate the process
If Name.Trim = "Notepad.exe" Then
    pMO.InvokeMethod("Terminate", Nothing)
    If (Me.MailEnabled) Then
'       Send the Email and then move it again to the processed Folder
        m_WMIWorkerOptions.EmailProperties.Message = pszOut
    End If
End If

The code in Listing 5 will validate that we have terminated a process and then place an e-mail notification in our SMTP mail queue. When the mail queue has been processed, the administrator or mail recipient will receive the notification.

Service Validation

When the code is installed and started, make sure that you create instances of the process that you want to not only terminate, but also receive notifications for. After the process has been terminated, you should see an Application log entry and also receive an e-mail notification about the termination.

Top 10
Extending LINQ to Objects : Writing a Single Element Operator (part 2) - Building the RandomElement Operator
Extending LINQ to Objects : Writing a Single Element Operator (part 1) - Building Our Own Last Operator
3 Tips for Maintaining Your Cell Phone Battery (part 2) - Discharge Smart, Use Smart
3 Tips for Maintaining Your Cell Phone Battery (part 1) - Charge Smart
OPEL MERIVA : Making a grand entrance
FORD MONDEO 2.0 ECOBOOST : Modern Mondeo
BMW 650i COUPE : Sexy retooling of BMW's 6-series
BMW 120d; M135i - Finely tuned
PHP Tutorials : Storing Images in MySQL with PHP (part 2) - Creating the HTML, Inserting the Image into MySQL
PHP Tutorials : Storing Images in MySQL with PHP (part 1) - Why store binary files in MySQL using PHP?
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 1)

- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 2)

- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 3)
Popular Tags
Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Biztalk Exchange Server Microsoft LynC Server Microsoft Dynamic Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Indesign Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe After Effects Adobe Photoshop Adobe Fireworks Adobe Flash Catalyst Corel Painter X CorelDRAW X5 CorelDraw 10 QuarkXPress 8 windows Phone 7 windows Phone 8 BlackBerry Android Ipad Iphone iOS