Tag Archives: MimboloveDashboard

How to Create a Squared Up Visio Dashboard for an Existing Distributed Application

Written by Tao Yang

Background

OK, it has been over a month since my last blog post. Not that I’ve been lazy, I’ve actually been crazily busy. As you may know, I’ve started working for Squared Up after Ignite. So, this is another blog about Squared Up – this time, I’ll touch base on the Visio dashboard.

If you haven’t heard or played with Squared Up’s Visio Dashboard plug-in, you can find a good demo by Squared Up’s founder, Richard Benwell in one of Microsoft Ingite’s SCOM Sessions here: https://www.youtube.com/watch?v=cUc2RSaoHtI

If you already have a Visio diagram for your application (that’s been monitored by OpsMgr), it is really quick and easy to import it into Squared Up as a dashboard (as Richard demonstrated in the Ignite session). However, what if you don’t have Visio diagrams for aparticular application you want to create dashboard for (i.e. an Off-The-Shelve application such as AD, ConfigMgr, etc.)? If this is the case, you can manually create the Visio diagram – and hopefully you are able to find the relevant stencils for your applications. But, this can take a lot of time. If you are like me, who really hate drawing Visio diagrams, you probably won’t enjoy this process too much.

In this post, I’ll show you how to quickly produce a Visio dashboard in Squared Up for an existing application that’s been monitored by SCOM. I’ll use the Windows Azure Pack Distributed Application from the community WAP management pack as an example (developed by Oskar Landman from Inovativ: http://www.systemcentercentral.com/windows-azure-pack-scom-management-pack/).

Walkthrough

01. In OpsMgr console, open the diagram view for the DA of your choice and export it to a Visio .vdx file:

image

Click OK if you get a message warning you there are too many objects included in this DA:

image

By default, the diagram view will only show the top level objects. However, you can keep drilling down the diagram, until you get a desired diagram (that you wish to display in Squared Up). In this demo, I will just use the diagram with top level objects:

image

As shown above, click the export button to export this diagram to a Visio diagram (.vdx) file.

02. Preparing the Visio diagram (.vsdx) from the .vdx file:

When you open the .vdx file, and zoom in, it looks exactly the same as the OpsMgr diagram view:

image

Firstly, you will need to remove the health state icons (the green ticks and red crosses in this case). A .vdx file is read-only in Visio, so after the icons have been removed, Save it as a .vsdx file. The .vsdx file looks like this now:

image

Now, we need to import SCOM monitoring objects data into this Visio diagram. Squared Up has written a good user guide on how to generate an Excel spreadsheet for the monitoring object information from Squared Up console. You can find this article here: http://support.squaredup.com/support/solutions/articles/207629-how-to-configure-a-visio-section-using-the-dashboard-designer

However, by using the Squared Up console as mentioned above, you have to manually  lookup every single monitoring object that is displayed in the Visio diagram. This can be very time consuming if you have a lot of objects in your diagram. In order to simplify this process, I have created a PowerShell script called Export-DAMembers.ps1 to get the information for members of a Distributed Application, and export the data to a CSV file.

You can download this script from HERE.

Note: This script does not require the native OpsMgr PowerShell module to run, however, it does require the OpsMgr 2012 SDK assemblies. If you are running it on an OpsMgr management server, web console server, or a computer that has the operational console installed, you don’t need to do anything else, you can just run this script straightaway. But if you are running this script on a computer that does not meet any of these requirements, you will need to copy the 3 OpsMgr 2012 SDK DLLs to the same folder of where the script is located. these 3 DLLs are:

  • Microsoft.EnterpriseManagement.Core.dll
  • Microsoft.EnterpriseManagement.OperationsManager.dll
  • Microsoft.EnterpriseManagement.Runtime.dll

image

You can find them on a management server, located at <OpsMgr install directory>\Server\SDK Binaries

I have included a help section for the script, as well as all the functions in the script, so I won’t go through how to use it here. you can simply open the script in a text editor and read it if you like:

SNAGHTML91a73e2

In order to export the information we need for the Visio dashboard, we only need the Display Name and the Monitoring Object Id. I’m running the script with the following parameters:

.\Export-DAMembers.ps1 -SDK “<SCOM Management Server Name>” -DADisplayName “Windows Azure Pack” -ExportProperties (“DisplayName”, “Id”) -Path C:\Temp\DAExport1.csv –verbose

image

Note: As you can see, because I’m only going to display the top level objects in the dashboard, so I did not have to use recursive lookup, therefore, only 6 objects returned. If I run the script again with “-recursive $true” parameter, it will return all objects that are member of the DA (143 in total):

image

The total number matches the previous warning message in the OpsMgr diagram view:

image

Once the CSV is exported, open it in Excel:

image

In order for Squared Up to understand the data, we will need to change the title for both columns:

  • Change DisplayName to ScomName
  • Change Id to ScomId

image

Now, save it as an Excel Spreadsheet (.xlsx file).

We can now import the data from the Excel spreadsheet into the Visio diagram. The guide from Squared Up’s site has documented it very well, I won’t go through it again here.

After I’ve mapped the data for each object in the Visio diagram, it looks like this:

image

I’ve then hidden the data in Visio, exported it as a .SVG file, and produced a Visio dashboard in Squared Up using the SVG file. The final piece looks like this:

image

Which is very similar to the diagram view in OpsMgr console:

image

Conclusion

If you already have Squared Up in your environment, I hope you find this blog post useful. As I demonstrated, it is really easy to create a Squared Up dashboard for your existing Distributed Applications – and I’ve already done the hard work for you (creating the script for looking up monitoring object IDs).

As we all know, Squared Up is based on HTML 5 and it’s cross platform, You can use it on browsers other than IE, as well as mobile devices such as an Android tablet. The picture below is my Lenovo Yoga Tab 2 Android tablet displaying this Squared Up WAP dashboard I’ve just created Smile

20150528_223322

OpsMgr Dashboard Fun: Server Details Using SquaredUp

Written by Tao Yang

After my previous post on how to create a performance view using SquaredUp, the founder of SquaredUp, Richard Benwell told me that I can also use “&embed=true” parameter in the URL to get rid of the headers. I also managed to create another widget to display server details. Combined with the performance view, I create a dashboard like this:

image

The bottom left is the improved version of the performance view (using embed parameter), and the right pane is the server details page:

SNAGHTML2d6fce9d

This server detail view contains the following information:

  • Alerts associated to the computer
  • Health states of the Distributed Apps that this computer is a part of.
  • Health State of its hosted components (Equivalent to the Health Explorer??)
  • Discovered properties of this computer

Combined with the performance view, it gives a good overview of the current state of the computer from different angles.

Here’s the script for this server detail view:

And here’s the script for the improved performance view (with “&embed=true” parameter):

I’d also like to clarify that my examples are just providing alternative ways to utilise SquaredUp and display useful information on a single pane of glass (dashboards).  I don’t want to mislead the readers of article to have an impression that SquaredUp relies on native OpsMgr consoles and dashboards. In my opinion and experience with SquaredUp, I think it is a perfect replacement to the built-in OpsMgr web console.

OpsMgr Dashboard Fun: Performance Widget Using SquaredUp

Written by Tao Yang

I’m a big fan of SquaredUp Dashboard. I have implemented it for my current “day-time” employer Coles over a year ago on their OpsMgr 2007 environments and we have also included SquaredUp in the newly built 2012 R2 management groups. In my opinion, it is more flexible than the native web console as it uses HTML 5 rather than Silverlight and it runs on any browsers as well as mobile devices.

One of my favourite features is that SquaredUp has the capability to directly read data from the OpsMgr Data Warehouse DB. Traditionally, OpsMgr operators would have to run or schedule reports in order to access aged performance data. Based on my experience, I think in 9 out of 10 times, it’s a total waste of my time, people don’t even open those reports when they arrived in their inboxes. With SquaredUp, you can access the performance data for any given period as long as it’s within the retention period. – So I can direct users to access these data from SquaredUp whenever they want, without having me involved.

I had some spare time today so I have installed the latest version in my home lab today. And I managed to create a dashboard using the PowerShell Web Browser widget for less than 10 minutes:

image

This dashboard contains 2 widgets. the left one is a state widget targeting Windows Server class. the widget on the right is a PowerShell Web Browser widget which has been made available since OpsMgr 2012 SP1 UR6 and SP2 UR2.

The script behind this widget is very simple. If you access the performance data of a server. the monitoring object ID and the timeframe are variables as part of the URL. so all I did is to pass these 2 variables. In this sample, I used the default timeframe of last 12 hours. you can specify other values if you like.

image

And here’s the script:

Additionally, in order to make SquaredUp work in this dashboard, I had to configure the Data Warehouse DB connection and enable Single Sign-On according to the instructions below:

 

If you haven’t played with SquaredUp yet, please have take a look at their website: www.squaredup.com. there’s an online demo you can access too.

OpsMgr 2012: A Trick to Drive Another Contextual Widget From PowerShell Grid Widget

Written by Tao Yang

PowerShell Grid widget and PowerShell Web Browser Widget were released as part of OpsMgr 2012 SP1 UR6 and R2 UR2. To me, these two widgets have opened a window of opportunities, because by using PowerShell, it allows OpsMgr 2012 users to customise and present the data exactly the way they wanted on dashboards.

Since it has been released, many people have share their work. Recently, Microsoft has started a new repository for the PowerShell widgets in TechNet Gallery.

The best article for the PowerShell Grid Widget that I have seen so far is from Oleg Kapustin’s blog: SCOM Powershell Grid Widget for Mere Mortals. In Oleg’s article (and seems to be a common practice), for each item that to be listed by the PowerShell Grid Widget, a unique Id is assigned to it (an auto incremented number):

image

Today, I want to share a small trick with you, something I’ve only picked up couple of days ago when I was writing the Location History dashboard for the 3rd part of my Location, Location, Location series. This is what the dashboard looks like:

SNAGHTML52cdecf

On this dashboard, users suppose to make their way from section 1 (state widget) to section 2 (PowerShell Grid Widget) and finally to section 3 (PowerShell Web Browser Widget). The PowerShell script in section 2 retrieves particular events generated by the object from section 1 using OpsMgr cmdlets, then display the data on this customised list. This script is listed below:

Param($globalSelectedItems)

$i = 1
foreach ($globalSelectedItem in $globalSelectedItems)
{
 $MonitoringObjectID = $globalSelectedItem["Id"]
 $MG = Get-SCOMManagementGroup
 $globalSelectedItemInstance = Get-SCOMClassInstance -Id $MonitoringObjectID
 $Computername = $globalSelectedItemInstance.DisplayName
 $strInstnaceCriteria = "FullName='Microsoft.Windows.Computer:$Computername'"
 $InstanceCriteria = New-Object Microsoft.EnterpriseManagement.Monitoring.MonitoringObjectGenericCriteria($strInstnaceCriteria)
 $Instance = $MG.GetMonitoringObjects($InstanceCriteria)[0]
 $Events = Get-SCOMEvent -instance $Instance -EventId 10001 -EventSource "LocationMonitoring" | Where-Object {$_.Parameters[1] -eq 4} |Sort-Object TimeAdded -Descending | Select -First 50
 foreach ($Event in $Events)
 {
 $EventID = $Event.Id.Tostring()
 $LocalTime = $Event.Parameters[0]
 $LocationStatus = $Event.Parameters[1]
 $Latitude = $Event.Parameters[2]
 $Longitude = $Event.Parameters[3]
 $Altitude = $Event.Parameters[4]
 $ErrorRadius = $Event.Parameters[5].trimend(".")
 
 $dataObject = $ScriptContext.CreateInstance("xsd://foo!bar/baz")
 $dataObject["Id"]=$EventID
 $dataObject["No"]=$i
 $dataObject["LocalTime"]=$LocalTime
 $dataObject["Latitude"]=$Latitude
 $dataObject["Longitude"]=$Longitude
 $dataObject["Altitude"]=$Altitude
 $dataObject["ErrorRadius (Metres)"]=$ErrorRadius
 $ScriptContext.ReturnCollection.Add($dataObject)
 $i++
 } 
}

 

Because I need to drive the contextual PowerShell Web Browser widget (section 3) from the PowerShell Grid Widget (section 2), the script used in section 3 needs to locate the exact event selected in section 2. As per Oleg’s article, based on his experiment, the only property passed between widgets is the “Id” property (of the data object). therefore, instead of using an auto increment number as the value for “Id” property as demonstrated in the previous screenshot from Oleg’s blog, I assigned the actual event Id as the data object Id so script in section 3 can use the event ID to retrieve data from the particular event.

From Section 2:

image

From Section 3:

image

Conclusion

Please keep in mind, the only property (and its value) for $globalselectedItems that travels between contextual widgets is “Id” property. if you want to drive another contextual widget based on the data passed from a PowerShell Grid Widget, please make sure you use the actual Id of the OpsMgr object (monitoring object, class, event, alert, etc…) so the next widget can use this Id to retrieve the object from OpsMgr.

New OpsMgr 2012 Dashboards Repository in TechNet Gallery

Written by Tao Yang

With the recent release of OpsMgr 2012 SP1 UR6 and R2 UR2, number of new dashboard widgets have been made available. The PowerShell Grid Widget and PowerShell Web Browser Widget are 2 of my favourite ones.

Microsoft has just created a new repository for the community to share their scripts and dashboards. This repository is located in the TechNet Gallery Script Center. You can access it from this direct link: http://bit.ly/Wy168U. or go to the script center and browse to: System Center > Operations Manager Dashboards:

image

Looks like the product team has already posted 4 samples in the first day. In the next few days, I will also post few of mine to this place. I encourage everyone to keep eye on this place from now on, and please do not hesitate to share your work with the community!

Location, Location, Location. Part 3

Written by Tao Yang

location-graphicThis is the 3rd and the final part of the 3-part series. In this post, I will demonstrate how do I track the physical location history for Windows 8 location aware computers (tablets and laptops), as well as how to visually present the data collected on a OpsMgr 2012 dashboard.

I often see people post of Facebook or Twitter that he or she has checked in at <some places> on Foursquare. I haven’t used Foursquare before (and don’t intend to in the future), I’m not sure what is the purpose of it, but please think this as Four Square in OpsMgr for your tablets Smile. I will now go through the management pack elements I created to achieve this goal.

Event Collection Rule: Collect Location Aware Device Coordinate Rule

So, I firstly need to collect the location data periodically. Therefore, I created an event collection rule targeting the “Location Aware Windows Client Computer” class I created (explained in Part 2 of this series). This rule uses the same data source module as the “Location Aware Device Missing In Action Monitor” which I also explained in Part 2. I have configured this rule to pass the exact same data to the data source module as what the monitor does, – so we can utilise Cook Down (basically the data source only execute once and feed the output data to both the rule and the monitor).

image

image

Note: Although this rule does not require the home latitude and longitude and these 2 inputs are optional for the data source module, I still pass these 2 values in. Because in order to use Cook Down, both workflows need to pass the exact same data to the data source module. By not doing this, the same script will run twice in each scheduling cycle.

This rule maps the data collected from the data source module to event data, and stores the data in both Ops DB and DW DB. I’ve created a event view in the management pack, you can see the events created:

SNAGHTMLb60c734

Location History Dashboard

Now, that the data has been captured and stored in OpsMgr databases as event data, we can consume this data in a dashboard:

SNAGHTMLb65f9e4

As shown above, there are 3 widgets in this Location History dashboard:

  • Top Left: State Widget for Location Aware Windows Client Computer class.
  • Bottom Left: Using PowerShell Grid widget to display the last 50 known locations of the selected device from the state widget.
  • Right: Using PowerShell Web Browser widget to display the selected historical location from bottom left PowerShell Grid Widget.

The last 50 known locations for the selected devices are listed on bottom left section. Users can click on the first column (Number) to sort it based on the time stamp. When a previous location is selected, this location gets pined on the map. So we known exactly where the device is at that point of time. – From now on, I need to make sure my wife doesn’t have access to OpsMgr in my lab so she can’t track me down Smile.

Note: the location shown in above screenshot is my office. I took my Surface to work, powered it on and connected to a 4G device, it automatically connected to my lab network using DirectAccess.

Surface in car

Since this event was collected over 2 days ago, for demonstration purpose, I had to modify the PowerShell grid widget to list a lot more than 50 previous locations.

The script below is what’s used in the bottom left PowerShell Grid widget:

Param($globalSelectedItems)

$i = 1
foreach ($globalSelectedItem in $globalSelectedItems)
{
$MonitoringObjectID = $globalSelectedItem["Id"]
$MG = Get-SCOMManagementGroup
$globalSelectedItemInstance = Get-SCOMClassInstance -Id $MonitoringObjectID
$Computername = $globalSelectedItemInstance.DisplayName
$strInstnaceCriteria = "FullName='Microsoft.Windows.Computer:$Computername'"
$InstanceCriteria = New-Object Microsoft.EnterpriseManagement.Monitoring.MonitoringObjectGenericCriteria($strInstnaceCriteria)
$Instance = $MG.GetMonitoringObjects($InstanceCriteria)[0]
$Events = Get-SCOMEvent -instance $Instance -EventId 10001 -EventSource "LocationMonitoring" | Where-Object {$_.Parameters[1] -eq 4} |Sort-Object TimeAdded -Descending | Select -First 50
foreach ($Event in $Events)
{
$EventID = $Event.Id.Tostring()
$LocalTime = $Event.Parameters[0]
$LocationStatus = $Event.Parameters[1]
$Latitude = $Event.Parameters[2]
$Longitude = $Event.Parameters[3]
$Altitude = $Event.Parameters[4]
$ErrorRadius = $Event.Parameters[5].trimend(".")

$dataObject = $ScriptContext.CreateInstance("xsd://foo!bar/baz")
$dataObject["Id"]=$EventID
$dataObject["No"]=$i
$dataObject["LocalTime"]=$LocalTime
$dataObject["Latitude"]=$Latitude
$dataObject["Longitude"]=$Longitude
$dataObject["Altitude"]=$Altitude
$dataObject["ErrorRadius (Metres)"]=$ErrorRadius
$ScriptContext.ReturnCollection.Add($dataObject)
$i++
}
}

 

And here’s the script for the PowerShell Web Browser Widget:

Param($globalSelectedItems)

$dataObject = $ScriptContext.CreateInstance("xsd://Microsoft.SystemCenter.Visualization.Component.Library!Microsoft.SystemCenter.Visualization.Component.Library.WebBrowser.Schema/Request")
$dataObject["BaseUrl"]="<a href="http://maps.google.com/maps&quot;">http://maps.google.com/maps"</a>
$parameterCollection = $ScriptContext.CreateCollection("xsd://Microsoft.SystemCenter.Visualization.Component.Library!Microsoft.SystemCenter.Visualization.Component.Library.WebBrowser.Schema/UrlParameter[]")
foreach ($globalSelectedItem in $globalSelectedItems)
{
$EventID = $globalSelectedItem["Id"]
$Event = Get-SCOMEvent -Id $EventID
If ($Event)
{
$bIsEvent = $true
$Latitude = $Event.Parameters[2]
$Longitude = $Event.Parameters[3]

$parameter = $ScriptContext.CreateInstance("xsd://Microsoft.SystemCenter.Visualization.Component.Library!Microsoft.SystemCenter.Visualization.Component.Library.WebBrowser.Schema/UrlParameter")
$parameter["Name"] = "q"
$parameter["Value"] = "loc:" + $Latitude + "+" + $Longitude
$parameterCollection.Add($parameter)
} else {
$bIsEvent = $false
}
}
If ($bIsEvent)
{
$dataObject["Parameters"]= $parameterCollection
$ScriptContext.ReturnCollection.Add($dataObject)
}

Conclusion

This concludes the 3rd and the final part of the series. I know it is only a proof-of-concept. I’m not sure how practical it is if we are to implement this in a corporate environment. i.e. Since most of the current Windows tablets don’t have GPS receivers built-in, I’m not sure and haven’t been able to test how well does the Windows Location Provider calculate locations when a device is connected to a corporate Wi-Fi.

I have also noticed what seems to be a known issue with the Windows Location Provider COM object LocationDisp.LatLongReportFactory. it doesn’t always return a valid location report. Therefore to work around the issue, I had to code all the scripts to retry and wait between attempts. I managed to get the script to work on all my devices. However, you may need to tweak the scripts if you don’t always get valid location reports.

Credit

Other than the VBScript I mentioned in Part 2, I was lucky enough to find this PowerShell script. I used this script as the starting point for all my scripts.

Also, when I was trying to setup DirectAccess to get my lab ready for this experiment, I got a lot of help from Enterprise Security MVP Richard Hick’s blog: http://directaccess.richardhicks.com. So thanks to Richard Smile.

Download

You can download the actual monitoring MP and dashboard MP, as well as all the scripts I used in the MP and dashboards HERE.

Note: For the monitoring MP (Location.Aware.Devices.Monitoring), I’ve also included the unsealed version in the zip file for your convenience (so you don’t have to unseal it if you want to look inside). Please do not import it into your management group because the dashboard MP is referencing it, therefore it has to be sealed.

Lastly, as always, I’d like to hear from the community. Please feel free to share your thoughts with me by leaving comments in the post or contacting me via email. Until next time, happy SCOMMING Smile.

Location, Location, Location. Part 2

Written by Tao Yang

miaThis is the 2nd part of the 3-part series. In this post, I will demonstrate how do I monitor the physical location of my location aware devices (Windows 8 tablets and laptops). To do so, I created a monitor which generates alerts when a device has gone beyond allowed distance from its home location. I will now go through each the component in the management pack that I created to achieve this goal.

Custom Class: Location Aware Windows Client Computer

I created a custom class based on “Windows Client 8 Computer” class. I needed to create this class instead of just using existing Windows Client 8 Computer class because I need to store 2 additional property values: “Home Latitude” and “Home Longitude”. Once been discovered, these 2 values will be passed to the monitor workflow so the script within the monitor can calculate the distance between current location and configured home location.

image

I created the following registry keys and values for this custom class:

Key: HKLM\SOFTWARE\TYANG\MonitorLocation

REG_SZ values: HomeLatitude & HomeLongitude

image

Discovery

I created a registry discovery targeting Windows Client 8 Computer class to discover the class (Location Aware Windows Client Computer) and the 2 properties I defined.

image

It is configured to run every 6 hours by default. This can be overridden.

Location Aware Device Missing In Action Monitor

image

image

To create this monitor, I firstly wrote a script to detect the current location and calculate the distance between the current location and home location (based on the registry value discovered).

Note: I managed to find few PowerShell scripts to calculate distance between 2 map coordinates (i.e. http://poshcode.org/2591 and http://stackoverflow.com/questions/365826/calculate-distance-between-2-gps-coordinates). However, I believe all the examples I found are not calculating the distance correctly. For example, I know for fact that the direct distance between my home to my office is somewhere between 23 – 25 kilometres. Using both of these scripts I mentioned, the calculated distance is around 16 kilometres. It is too short to be considered being correct. In the end, I found a VBScript from a Unix forum. The result from this script is just over 23km, which also matches the result from this online calculator. Therefore, I converted this VBScript into PowerShell and used it in this management pack. As I am really bad at math, I didn’t bother looking into the differences between these scripts. It is beyond my ability.

When the script runs, it logs an informational event (event ID 10003) if the current location is successfully detected:

SNAGHTMLb37b568

Or a warning event (event ID 10002) if the location data retrieved is not valid.

I then created Probe Action, Data Source modules and monitor type for this monitor. – All just usual drill, I won’t go through the details here.

As I have shown in the 1st and 2nd screenshots, I have configured required registry keys and values on my wife’s Dell XPS ultrabook (running Windows 8.1). The Home Latitude and Longitude coordinates are the location of my office. Because I configured the warning threshold to 5,000 metres (5km) and critical threshold to 10,000 metres (10km), a critical alert was generated against this XPS laptop:

SNAGHTMLb381a0e

For my Surface Pro 2, I configured the home location to be my home, therefore, currently as I’m home writing this blog post and it is right next to me, the health state for my Surface is healthy:

SNAGHTMLb3e690c

This concludes the 2nd part of the series. Please continue to Part 3.

Location, Location, Location. Part 1

Written by Tao Yang

iStock_000006260161SmallYes, I am starting to write a 3 part series on this topic: Location, Location, Location. It is not about real estate business – It would be silly for me to wait until I’ve received MVP award to become a real estate salesman, right? Smile

This series is all about tracking physical location for Windows based mobile devices (tablets and laptops). It involves windows tablets/ laptops, OpsMgr 2012, dashboards, Google Maps and Windows Location Platform. Does this interest you? if so, please continue reading. Smile

Background

When I started designing the OpsMgr 2012 infrastructure for my employer about a 18 months ago, during requirements gathering phase, Windows tablets were seriously in the scope of devices to be monitored by OpsMgr. At that time, I thought it doesn’t make any sense having OpsMgr 2012 to monitor thousands of Windows tablets. Now, 18 months later, with more and more organisations started to adopt Windows 8 tablets into corporate environments, I thought I’d spend a little bit time on this and see what we can get out of OpsMgr if Windows 8 tablets and laptops are being monitored in OpsMgr 2012.

Since most of the modern devices are location aware, wouldn’t it be nice if we can use SCOM to monitor their physical locations? I had this idea after I posted the Google Map dashboard couple of months ago. Now that FIFA World Cup is over and my life is back to normal, I finally had time to spend on it.

Introduction

One important aspect of tablets and laptops is being mobile. physical security has always been a big concern for organisations. By utilising Windows Location Framework, OpsMgr agent and dashboards, I managed to produce 3 scenarios in my lab. I will cover each one of them in one part of this series:

  • Part 1: Track Windows 8 computers current location (real time)
  • Part 2: Monitor the physical location (In case it’s gone M.I.A)
  • Part 3: Track historical locations (where have they been?)

Note: The management packs I created for this experiment can be downloaded at the end of part 3.

Pre-requisites

To prepare my lab of these monitoring scenarios, I had to setup the following pre-requisites:

01. Setup DirectAccess for my home lab so my Surface Pro 2 would automatically connect to my lab when it is not at home (i.e. via a 4G connection).

02. Rebuilt my Surface Pro 2 to Windows 8.1 Enterprise edition. – As DirectAccess client is only available in Enterprise edition.

03. Made sure Windows Location Platform is enabled on Surface Pro 2. This is configured in Control Panel:

image

and Privacy settings:

image

We can also use GPO to enable it: Computer Configuration\Administrative Templates\Windows Components\Location and Sensors

image

04. Make sure WinRM is enabled on the mobile devices. A PowerShell script I used in a dashboard uses WinRM to get the devices location report.

Additionally, I already have OpsMgr 2012 R2 agent installed on my Surface Pro 2 and it is reporting to my home management group. The latest OpsMgr 2012 Update Rollup (SP1 UR6 or R2 UR2) also needs to be installed in order to use the new PowerShell dashboard widgets.

Limitations – Lack of GPS Devices

When I started working on this experiment, I found my Surface Pro 2 does not have a GPS receiver (And Surface Pro 3 also doesn’t have it Sad smile). Then I also found most of the Windows 8 tablets currently out in the market don’t have GPS receivers built-in. I haven’t been able to find one with GPS receivers. Therefore, the location data provided by Windows Location API come from Wi-Fi triangulation, IP address resolution and cellular network triangulation, which is probably less accurate than GPS data (More details can be found on MSDN:http://msdn.microsoft.com/en-us/library/windows/apps/hh464919.aspx). I didn’t want to purchase a Windows 8 compatible GPS receiver because I have no real need for it after this experiment, and also tried to use my Android phone as a bluetooth GPS receiver to the Windows 8 devices, but I couldn’t make it work.

Having said that, based on my experience, the data received from cellular and Wi-Fi network is fairly accurate for me. When I’m at home, the location on the map is my neighbour across the road, which is less than 20 metres away from my desk.

Scenario 1: Where is the the device currently located?

I created a fairly simply dashboard in OpsMgr to pinpoint the current location of a selected:

SNAGHTMLa18e258

(Sorry guys, I pixelated the map as I don’t really want to post my home location on the Internet Smile).

As you can see, this dashboard only contains 2 widgets. the left widget is a state widget targeting “Windows Client 8 Computer” class:

SNAGHTMLa1bd8f3

SNAGHTMLa1c63fd

SNAGHTMLa1ced71

Note: Because I’m referencing Windows 8 computers, I have Windows 8 management packs (version 6.0.7024.0) loaded in my management group. Since all the client computers in my lab are running 8.1, I have also installed the Windows 8 Addendum MP from Kevin Holman as the original one does not discover Windows 8.1.

The widget on the right is a PowerShell Web Browser widget (shipped with SP1 UR6 and R2 UR2). This widget runs the script below:

Param($globalSelectedItems)
$dataObject = $ScriptContext.CreateInstance("xsd://Microsoft.SystemCenter.Visualization.Component.Library!Microsoft.SystemCenter.Visualization.Component.Library.WebBrowser.Schema/Request")
$dataObject["BaseUrl"]="<a href="http://maps.google.com/maps&quot;">http://maps.google.com/maps"</a>
$parameterCollection = $ScriptContext.CreateCollection("xsd://Microsoft.SystemCenter.Visualization.Component.Library!Microsoft.SystemCenter.Visualization.Component.Library.WebBrowser.Schema/UrlParameter[]")
foreach ($globalSelectedItem in $globalSelectedItems)
{
$globalSelectedItemInstance = Get-SCOMClassInstance -Id $globalSelectedItem["Id"]
$DNSNameProperty = $globalSelectedItemInstance.GetMonitoringProperties() | Where-Object {$_.name -match "^DNSName$"}
$DNSName = $globalSelectedItemInstance.GetMonitoringPropertyValue($DNSNameProperty)

#Get Coordinates via WinRM

#Create a WinRM session to the remote computer
$RemoteSession = New-PSSession -ComputerName $DNSName
$objRemoteLoc = Invoke-command -scriptblock {
# Windows Location API
$mylocation = new-object -comObject LocationDisp.LatLongReportFactory
#$mylocation.ListenForReports(1000)

# Get Status
$mylocationstatus = $mylocation.status

#try again if first attemp is not successful
if ($mylocationstatus -ne 4)
{
#Remove-Variable mylocation
Start-Sleep -Seconds 5
$mylocation = new-object -comObject LocationDisp.LatLongReportFactory
$mylocationstatus = $mylocation.status
}
If ($mylocationstatus -eq 4)
{
# Windows Location Status returns 4, so we're "Running"
# Get Latitude and Longitude from LatlongReport property
$latitude = $mylocation.LatLongReport.Latitude
$longitude = $mylocation.LatLongReport.Longitude
$altitude = $mylocation.LatLongReport.altitude
$errorRadius = $mylocation.LatLongReport.ErrorRadius
}

#Pass invalid values if location is not detected
If ($latitude -eq $null -or $longitude -eq $null)
{
$bValidLoc = $false
} else {
$bValidLoc = $true
}

#Return Data
$objLoc = New-Object psobject
Add-Member -InputObject $objLoc -membertype noteproperty -name "ValidLocation" -value $bValidLoc
Add-Member -InputObject $objLoc -membertype noteproperty -name "LocationStatus" -value $mylocationstatus
Add-Member -InputObject $objLoc -membertype noteproperty -name "latitude" -value $latitude
Add-Member -InputObject $objLoc -membertype noteproperty -name "longitude" -value $longitude
Add-Member -InputObject $objLoc -membertype noteproperty -name "altitude" -value $altitude
Add-Member -InputObject $objLoc -membertype noteproperty -name "errorRadius" -value $errorRadius
$objLoc
} -Session $RemoteSession
$latitude = $objRemoteLoc | select -ExpandProperty latitude
$longitude = $objRemoteLoc | select -ExpandProperty longitude
$ValidLocation = $objRemoteLoc | select -ExpandProperty ValidLocation
$parameter = $ScriptContext.CreateInstance("xsd://Microsoft.SystemCenter.Visualization.Component.Library!Microsoft.SystemCenter.Visualization.Component.Library.WebBrowser.Schema/UrlParameter")
$parameter["Name"] = "q"
$parameter["Value"] = "loc:" + $latitude + "+" + $longitude
$parameterCollection.Add($parameter)
Remove-PSSession $RemoteSession
}
$dataObject["Parameters"]= $parameterCollection
$ScriptContext.ReturnCollection.Add($dataObject)

This script establishes a PS Remote session (WinRM) and retrieve computer’s coordinates using LocationDisp.LatLongReportFactory COM object. the coordinates then get passed back to the local PS session and then got pinned on Google Map based on the latitude and longitude data.

This concludes part 1 of the series. Please continue to Part 2.

Controlling OpsMgr 2012 PowerShell Contextual Script Widgets Behaviour

Written by Tao Yang

Few days ago I posted an OpsMgr 2012 dashboard using Google Maps. After it’s been posted, I noticed there is a minor issue with the dashboard.

When I click on a monitoring object from the top left “Remote Computers” state widget, the “Map” widget on the right refreshes and loaded the map based on the location property values of the remote computer class:

image

But when I click on an object in the bottom left “Component” widget (which is a list of related objects of remote computer class), the map refreshes again. Only this time, because the locations cannot be found from object properties, it passed an empty string to Google Map:

image

This is because the “Map” widget uses a contextual PowerShell Web Browser Widget. a contextual widget gets data from other widgets within the dashboard and it is updated when objects of another widget is selected.

So, in order to overcome this issue, I have updated script used by the PowerShell Browser Widget for the map, to check if the selected object belongs to a specific class, if not, don’t return any data (thus the web page will not be reloaded and will remain the same.)

Here’s the updated script:

Param($globalSelectedItems)

#Function to Check If the monitoring object belongs to a specific class
Function Validate-ObjectClass ($MonitoringObjectID, $ClassName)
{
$ClassId = (Get-SCOMClass -Name "$ClassName").Id
$MObject = Get-SCOMMonitoringObject -Id $MonitoringObjectID
$bvalid = $false
Foreach ($Id in $MObject.MonitoringClassIds)
{
If ($Id -eq $ClassId)
{
$bvalid = $true
}
}
$bValid
}

$dataObject = $ScriptContext.CreateInstance("xsd://Microsoft.SystemCenter.Visualization.Component.Library!Microsoft.SystemCenter.Visualization.Component.Library.WebBrowser.Schema/Request")
$dataObject["BaseUrl"]="<a href="http://maps.google.com/maps&quot;">http://maps.google.com/maps"</a>
$parameterCollection = $ScriptContext.CreateCollection("xsd://Microsoft.SystemCenter.Visualization.Component.Library!Microsoft.SystemCenter.Visualization.Component.Library.WebBrowser.Schema/UrlParameter[]")
$bAllValid = $true #Assuming all selected objects are valid
foreach ($globalSelectedItem in $globalSelectedItems)
{
#Save the monitoring object ID into a variable
$MObjectID = $globalSelectedItem["Id"]
#Check if a "Demo.Remote.Computers.Remote.Computer.Class" object is selected
$bValidOBject = Validate-ObjectClass $MObjectID "Demo.Remote.Computers.Remote.Computer.Class"
If ($bValidOBject)
{
#Valid object, continue building URL parameters
$globalSelectedItemInstance = Get-SCOMClassInstance -Id $MObjectID
$MProperties = $globalSelectedItemInstance.GetMonitoringProperties()
$StreetProperty = $MProperties | Where-Object {$_.name -match "Street"}
$CityProperty = $MProperties | Where-Object {$_.name -match "City"}
$StateProperty = $MProperties | Where-Object {$_.name -match "State"}
$CountryProperty = $MProperties | Where-Object {$_.name -match "Country"}
$Street = $globalSelectedItemInstance.GetMonitoringPropertyValue($StreetProperty)
$City = $globalSelectedItemInstance.GetMonitoringPropertyValue($CityProperty)
$State = $globalSelectedItemInstance.GetMonitoringPropertyValue($StateProperty)
$Country = $globalSelectedItemInstance.GetMonitoringPropertyValue($CountryProperty)
$parameter = $ScriptContext.CreateInstance("xsd://Microsoft.SystemCenter.Visualization.Component.Library!Microsoft.SystemCenter.Visualization.Component.Library.WebBrowser.Schema/UrlParameter")
$parameter["Name"] = "q"
$parameter["Value"] = "$street $City $state $Country"
$parameterCollection.Add($parameter)
} else {
#the object is not a valid object, therefore set "All Valid" boolean variable to false
$bAllValid = $false
}
}
#only return data when all selected objects are valid
If ($bAllValid)
{
$dataObject["Parameters"]= $parameterCollection
$ScriptContext.ReturnCollection.Add($dataObject)
}

The highlighted sections are what’s changed from the original script:

image

Now, I created another dashboard using the code above, when clicked on a related object from bottom left widget, nothing happens on the map widget. the map remains the same:

image

I put the code for the validation into a separate function Validate-ObjectClass so this function can be reused in other widgets and dashboard. You may use this function when there are more than 2 widgets in a dashboard and you only want a PowerShell contextual widget to refresh when a specific type of object is selected from other widgets.

I hope you find this blog post and script useful, please feel free to contact me if you have any questions or concerns.

OpsMgr Dashboard Fun: Google Maps

Written by Tao Yang

I am really excited about the 2 new PowerShell dashboard widget released in OpsMgr 2012 R2 UR2. PowerShell has always been my favourite scripting language, something I have been using on a daily basis since 2008. In my opinion, the opportunities are endless when having the ability to execute PowerShell scripts within an OpsMgr dashboard. I will start posting my ideas in this blog.

Background

For those who don’t know me, I work for an Australian retailer which has 3 brands (supermarkets, service stations and liquor stores) with totally over 2000 stores across the country. Pretty much every Windows device in the stores are being managed by System Center. Because of the nature of the environment we are in, in the past, there were ideas tossing around in the office that people really like to have some kind of map dashboard for OpsMgr, and we have trailed / tested different solutions. Although there are 3rd party solutions out there, yesterday, I have spent couple of hours and created a dashboard like this:

image

This dashboard contains:

  • Top Left: State widget for a customized class called “TYANG Remote Computer”, which is based on Windows Computer class.
  • Bottom Left: Contextual PowerShell Grid widget displays health state of all related objects for “TYANG Remote Computers”
  • Right: Contextual PowerShell Web Browser widget that pin-points the computer location on Google Maps.

In Action:

I’ll now go through the steps I took to make this dashboard work. the management packs I used in the demo can also be downloaded from the link at the end of this post.

Instructions

Step 01. Create a management pack to define and discover the custom Windows Computer class.

I Named this management pack “Demo.Remote.Computers”. I basically created a customized Windows Computer class with 4 additional properties:

  • Street
  • City (aka Suburb as what we call in Australia)
  • State
  • Country

image

I then created a registry key and stored these property values in the key:

image

After creating the registry key on few machines, I then created a filtered registry discovery workflow in the MP. It targets Windows Computer class and it is looking for this key. It also maps the 4 reg key values I created to the class properties.

Lastly, before I sealed the MP, I also created a folder and a state view for this custom class. The Accessibility of the folder is set to “Public” – so later on I can place the dashboard under this folder from a separate MP.

image

Step 02. Create the dashboard

Now that the class is defined and discovered, I can move on to the dashboard. To create the dashboard, firstly, I created a brand new MP from the Operations console, and called it “Demo Remote Computer Dashboard” with the ID “Demo.Remote.Computer.Dashboard”. When the unsealed MP is created in the operations console, a folder is automatically created with the MP. I will place the dashboard under this folder (for now):

image

I gave the dashboard a name and chose an appropriate dashboard layout :

SNAGHTML22e2dfb6SNAGHTML22e37454

I added a state widget for the top left pane

SNAGHTML22e4fb14

Gave it a name: “Remote Computers”

SNAGHTML22e5ef28

Choose the class I have defined in Step 1

SNAGHTML22e6ece1

I want to display all instances, so I did not select anything in the Criteria step:

SNAGHTML22e82adf

I defined what I property that I want to display, and how to sort the instances:

image

Then click Next and Create to create the widget.

image

Next, I’ll create a PowerShell Grid contextual widget in the bottom right section to display the health of each related components.

Choose “PowerShell Grid Widget”

SNAGHTML22ed3e40

Name: “Components”

SNAGHTML22ee6098

Add the script below to the script section:

SNAGHTML22ef9a12

Param($globalSelectedItems)
foreach ($globalSelectedItem in $globalSelectedItems)
{
$globalSelectedItemInstance = Get-SCOMClassInstance -Id $globalSelectedItem["Id"]
foreach ($relatedItem in $globalSelectedItemInstance.GetRelatedMonitoringObjects())
{
$ClassName = $relatedItem.GetMonitoringclasses()[0].DisplayName
$dataObject = $ScriptContext.CreateFromObject($relatedItem, "Id=Id,State=HealthState,DisplayName=DisplayName,FullName=FullName", $null)
$dataObject["ParentRelatedObject"] = $globalSelectedItemInstance.DisplayName
$ScriptContext.ReturnCollection.Add($dataObject)
}
}

Click Next and Create to create the widget.

SNAGHTML22f0d6d8

Lastly, I’ll create a PoweShell Web Browser contextual widget for the map on the right section.

Choose PowerShell Web Browser Widget

SNAGHTML22f274d8

Name it “Map”

SNAGHTML22f3613c

Copy the script below to the script section:

SNAGHTML22f4ac2b

Param($globalSelectedItems)
$dataObject = $ScriptContext.CreateInstance("xsd://Microsoft.SystemCenter.Visualization.Component.Library!Microsoft.SystemCenter.Visualization.Component.Library.WebBrowser.Schema/Request")
$dataObject["BaseUrl"]="http://maps.google.com/maps"
$parameterCollection = $ScriptContext.CreateCollection("xsd://Microsoft.SystemCenter.Visualization.Component.Library!Microsoft.SystemCenter.Visualization.Component.Library.WebBrowser.Schema/UrlParameter[]")
foreach ($globalSelectedItem in $globalSelectedItems)
{
$globalSelectedItemInstance = Get-SCOMClassInstance -Id $globalSelectedItem["Id"]
$StreetProperty = $globalSelectedItemInstance.GetMonitoringProperties() | Where-Object {$_.name -match "Street"}
$CityProperty = $globalSelectedItemInstance.GetMonitoringProperties() | Where-Object {$_.name -match "City"}
$StateProperty = $globalSelectedItemInstance.GetMonitoringProperties() | Where-Object {$_.name -match "State"}
$CountryProperty = $globalSelectedItemInstance.GetMonitoringProperties() | Where-Object {$_.name -match "Country"}
$Street = $globalSelectedItemInstance.GetMonitoringPropertyValue($StreetProperty)
$City = $globalSelectedItemInstance.GetMonitoringPropertyValue($CityProperty)
$State = $globalSelectedItemInstance.GetMonitoringPropertyValue($StateProperty)
$Country = $globalSelectedItemInstance.GetMonitoringPropertyValue($CountryProperty)
$parameter = $ScriptContext.CreateInstance("xsd://Microsoft.SystemCenter.Visualization.Component.Library!Microsoft.SystemCenter.Visualization.Component.Library.WebBrowser.Schema/UrlParameter")
$parameter["Name"] = "q"
$parameter["Value"] = "$street $City $state $Country"
$parameterCollection.Add($parameter)
}
$dataObject["Parameters"]= $parameterCollection
$ScriptContext.ReturnCollection.Add($dataObject)

Click Next and Create to create the widget.

The dashboard should be fully functional by now.

image

You can stop now, or continue on to the next step to use the GTM tool to generalize the dashboard MP – if you want to use this dashboard in other management groups.

Step 03: Generalizing the Dashboard MP

Firstly, export the dashboard MP, but do not delete it from the management group after export.

Run the GTMTool.exe against the exported MP. When asked if I want to create a task pane dashboard, answer “Y” and enter the name of the MP I created in step 01 (“Demo.Remote.Computers”).

image

Although it’s not required, but I also opened the MP generated by the GTMTool.exe, replaced all the “UIGenerated” strings with something meaningful.

Before:

image

After:

image

Lastly, delete the old dashboard MP in OpsMgr, and import the updated one. The dashboard can now be found under the folder from the MP created in step 01.

image

Issues I experienced

01. Google Maps VS. Bing Maps

Someone may want to ask, why did I choose Google Maps rather than Microsoft’s Bing Maps. Well, I’m not sure about other countries, but couple of years ago when I was testing a well known OpsMgr map dashboard, which uses Bing Map (you probably know which one I’m talking about), I found the mapping data for Australia is very inaccurate.

For example, when I searched my local supermarket using address, Google Maps had no problem pin-pointing it in the map, but Bing maps could not find it:

Google Maps:

image

Bing Maps:

image

You can argue that I live in a Melbourne’s outer suburb, it is approx. 50km away from CBD and I can see horses and cows on a daily basis. Bing can be accurate for metropolitan areas or famous tourist attractions.

i.e. the supermarket located in Bondi Junction, NSW, near the famous Bondi Beach:

Google Maps finds it:

image

Bing Maps also finds it:

image

But for me employer, who operates all over Australia including areas very remote, it’s clearly an issue – unless we use map co-ordinates instead of addresses.

02. Google Maps Script Error:

While I was configuring Google Map widget, I also had an issue that I always get a script execution error from IE:

image

After spending some time googling this error, I learned Google does not work well with certain versions of IE. This leads to an issue that could be a common issue with the PowerShell Web Browser Widget. I managed to identify and fix the error, I’ll cover the issue and the fix in a separate post, because I believe this error can happen for other web sites.

03. Google Maps left pane

I tried to find a way to disable it, but in many online forums, people said there is no way to disable it unless use it in an iframe with the parameter “out=embed” in the URL.

image

I’m not a web developer, but I’m guessing if I develop a web page on a web server to host such an iframe, I should be able to remove it? it’s just a thought, I haven’t looked into it.

Anyways, after playing with it for a while, I don’t really mind clicking the arrow to minimise the left pane every time, having the left pane there can be handy sometimes as I can also use the “Get Directions” function as I demonstrated in the video.

Conclusion

Overall, I spent more time trying to get Google Maps working in the widget than time creating the management pack and dashboard. The management packs can be downloaded HERE.

Please keep in mind the MP that defines and discovers your classes must be sealed so other MPs can reference it. I’ve included both sealed and unsealed version of this MP, if you want to test it out in your environment, please make sure you used the sealed version (Demo.Remote.Computers.mp).

I did not seal the dashboard MP so it is easier for you to see what’s under the hood.