MDT Monitoring Deep Dive IV – Sending more information
In my post MDT Monitoring Deep Dive II – Consuming the data yourself, I showed you how you can write your own web service, that consumes the MDT monitoring information. The next thing we will cover is, how we can send even more information from MDT and also make use of a pretty hidden feature in this monitoring option I blogged about in the last post.
Send additional information
As we have seen in the last couple of posts, MDT will automatically send some information about the current deployment status to a web service. Which it then uses to monitor the deployment. It covers some basic information like the current step and step name, any errors or warnings, current IP address, etc. But what if we would like to receive more information like ServiceTag/AssetTag for some custom identification, the Task Sequence ID it’s currently running, the deployment method or probably some custom property.
Now as we have created a custom web service, it should be a piece of cake. Just add a new parameter to the “PostSettings” method in the web service, and then add this parameter to the web service call in the ZTIUtility.vbs script.
Well, that works, but you would have to redo this, whenever you want to add a new parameter and also whenever you upgrade or install MDT. While it’s generally a bad idea to change the original MDT files, a single change might be worth the effort, but ending up with multiple versions could create some headache. What I’m going to demonstrate now is a more generic way of adding new properties to our Monitoring.
Let’s start with the MDT part first. The idea here is to create a new MDT List property, that holds a list of all additional properties, that shall be included in the web service call. We can then add them on the fly, even dynamically based on other values. On each web service call, MDT just loops through this list and adds an entry for each property.
For reason of simplicity, I call the list “MonitorProperties”. To define them for our deployment, we just add it to our customsettings.ini:
1 2 3 |
[Settings] Priority=Init,....,Default Properties=MonitorProperties(*) |
the “(*)” tells MDT, that this custom property shall be treated as a list. Now we can add a couple properties to this new list
1 2 3 4 5 6 |
[Init] MonitorProperties001=ServiceTag MonitorProperties002=SerialNumber MonitorProperties003=TaskSequenceID MonitorProperties004=Model ... |
So far nothing really fancy. However, we need to make a small change to the ZTIUtility.vbs, otherwise no additional information will be send. In the ZTIUtility.vbs file, we search for the function called “CreateEvent”. In the second part of the function, it’s preparing the web service call (see This post for details). Just after MDT has prepared all its original information but right before it’s sending them, we add the following lines (in MDT 2012 and MDT 2012 Update 1 insert it at line 404)
1 2 3 4 |
' Add additional parameters specified in MonitorProperties Dim sMonProp For Each sMonProp In oEnvironment.ListItem("MonitorProperties").Keys sLine = sLine & "&" & sMonProp & "=" & oEnvironment.Item(sMonProp) Next |
It should be pretty self-explaining. It just loops through the list of additional properties and for each property, it just adds the name and the configured value to the URL, which is sent to the web service. With this approach, we can influence what is being sent even during runtime, and it doesn’t have any negative side-effect. If nothing is configured, no changes will be applied.
Updating the web service
Well, this was the MDT side of things. Now we need to consume those additional information. To keep things simple, we make use of the Request.QueryString object. It contains the query string from the requested URL and by this gives us a list of all keys and values that have been sent. Now we create two lists, one with the original MDT properties and one that holds the custom ones. In your own solution, you most probably going to have just one, but for demonstration purposes, it’s a nice way of collecting them.
So all I do is I define a new class that contains all the original MDT properties
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Public Class MDTDefaultMonitoringModel Public Property uniqueID As String Public Property computerName As String Public Property messageId As String Public Property severity As String Public Property stepName As String Public Property currentStep As Short? Public Property totalSteps As Short? Public Property id As String Public Property message As String Public Property dartIP As String Public Property dartPort As String Public Property dartTicket As String Public Property vmHost As String Public Property vmName As String End Class |
Then I can use this class as the parameter of my function, making use of a feature of ASP.Net MVC that maps each key from the query string to a corresponding property. Giving us a single object to work with.
1 2 3 4 5 |
Function PostEvent(DefaultProps As MDTDefaultMonitoringModel) As ActionResult ... End Function |
If we use only the default properties, we are done now. To add our custom properties, we could either simply extend the above shown class, or we also make it a bit more generic and keep them in a list. As we need to assemble all parameters for our forwarded call to the original MDT Web service anyway, let’s use it to fill a list with all default properties.
1 2 3 4 5 6 7 8 9 10 11 12 |
Private _DefaultProperties As New Dictionary(Of String, String) ... Dim param As String = String.Empty ' Prepare parameter string For Each prop As PropertyDescriptor In TypeDescriptor.GetProperties(DefaultProps) ' Fill a dictionary with all default MDT properties for performance reasons _DefaultProperties.Add(prop.Name, prop.GetValue(DefaultProps)) param &= String.Format("&{0}={1}", prop.Name, HttpUtility.UrlEncode(_DefaultProperties(prop.Name))) Next |
Then we just take the rest and add them to an additional list, that contains our custom properties.
1 2 3 4 5 6 |
' Get additional custom properties For Each prop In Request.QueryString.Keys If Not _DefaultProperties.ContainsKey(prop) Then _CustomProperties.Add(prop, Request.QueryString(prop)) End If Next |
Looks like an ugly way of doing this, but as mentioned before, this is only for demonstration purposes. So the main target is, to just get it working.
Now we would need to store or use this information somehow. In the next post, we will create a small database, that stores this information for further usage and also gives us the same information like the workbench in a web page.
Returning Settings back to the Client
To finalize this post, we want to add the “GetSettings” function to our demo web service. As mentioned in my last post, it’s being queried by the gather process as soon as you switch on the monitoring feature. So without this function, you will regularly see some errors in your logs.
As we did with the the former function, we could also just pass this information to the original MDT web service and send the result back to the client. But as I found this feature pretty hard to use and configure with the default MDT implementation, let’s preserve this for future usage and just return a sample string for now, to prove that it’s working. For demonstration purposes I return a “HelloWorld” for a custom property called “MonitorResult”
1 2 3 4 5 |
Function GetSettings(uniqueID As String) As ActionResult Return New XmlResult(New GetSettingsResultModel With {.MonitorResult = "HelloWorld"}) End Function |
Looking at the log you can see, the gather process is now querying our custom Monitoring web service (which runs here on a different port than the MDT web service) and stores the result in the custom “MonitorResult” property.
Find the download with the compiled web service and the updated ZTIUtility.vbs file on CodePlex. The source files can also be found on CodePlex in the “Source Code” section. You might want to use a source control client like TortoiseSVN and point it to https://mdtcustomizations.svn.codeplex.com/svn/Demo/MDT_MonitoringService/Current.
In the next post, we will build upon what we have covered so far and move towards a more useful web service that stores and displays the information.
Recent Comments