Menu Close

SCOM Dashboards – Using the PowerShell Grid Widget

This post will give some very basic examples on how to get started using PowerShell Grid Widgets.

PowerShell grid widgets in SCOM dashboards are really powerful, but hard to understand and therefore difficult to use.  There are not many good examples on the web anymore.  We need to start somewhere – so lets start with some real basic concepts.

Documentation:  Operations Manager Dashboard Script Widgets – TechNet Wiki

PowerShell Grid Widgets run a PowerShell script in the console, as the user logged into the console.  The scripts connect to the SCOM SDK, but they do not execute on the management server, they execute on the machine where the console is installed.

These examples will work in the Dashboards available in the SCOM console, and in the SCOM 2019 and later HTML5 Web console PowerShell Widgets.

 

Dashboard of all Windows Computers in SCOM

Here is a very basic example of getting a list of all the Windows Computer objects in SCOM:

# Get the class by Name $Class = Get-SCOMClass -Name "Microsoft.Windows.Computer" # Get all instances of the class $Instances = Get-SCOMClassInstance -Class $Class #Loop through each instance of the class FOREACH ($Instance in $Instances) { #Add to the output for display in dashboard $ServerName = $Instance.DisplayName.ToString() # Create a data object using a dummy object type $dataObject = $ScriptContext.CreateInstance('xsd://foo!bar/baz') #Create an ID used for sorting the output - Must be a string value - Used to sort the grid $dataObject['Id'] = $ServerName # Add the rest of the desired properties $dataObject['State'] = $ScriptContext.CreateWellKnownType('xsd://Microsoft.SystemCenter.Visualization.Library!Microsoft.SystemCenter.Visualization.OperationalDataTypes/MonitoringObjectHealthStateType',$Instance.HealthState.value__) $dataObject['ServerName'] = $ServerName # Add the data object to be displayed in the dashboard $ScriptContext.ReturnCollection.Add($dataObject) }

In the SCOM Console, select the “My Workspace” pane, and create a new Dashboard View.

image

Choose Grid Layout, and give it a name like “Computers

image

Choose “1 Cell” and select the cell.

image

Click “Create”.

Select your Computers Dashboard and Click to add a Widget.  Choose the PowerShell Grid Widget

image

Give the Widget a name such as “Computer List

image

Next, paste in the script from above.

image

This results in a dashboard that is a simple list of the Windows Computers in the SCOM Management Group:

image

Note that you can sort by Computer Name or by Health State in this Example.

Also note – you cannot drill down or see Health Explorer from this list.  This is because we used a PowerShell script that returned a simple list.  Not an array of SCOM Objects.

So next, lets return actual SCOM objects!

 

Dashboard of Windows Computer OBJECTS in SCOM

The only difference will be a small change in the PowerShell Script:

# Get the class by Name $Class = Get-SCOMClass -Name "Microsoft.Windows.Computer" # Get all instances of the class $Instances = Get-SCOMClassInstance -Class $Class #Loop through each instance of the class FOREACH ($Instance in $Instances) { $dataObject = $ScriptContext.CreateFromObject($Instance,"Id=Id,HealthState=HealthState,DisplayName=DisplayName",$null) # Add the data object to be displayed in the dashboard $ScriptContext.ReturnCollection.Add($dataObject) }

This example uses  ScriptContext CreateFromObject method to return actual objects instead of a dummy list.

The key difference here is that since we are returning an array of Windows Computer objects to the dashboard, we can use Tasks, Right-Click navigation, Entity properties, Reports, etc.

image

 

Dashboard of objects filtered by a Group

Now, what about a filtered view?

Such as, Windows Computer objects in a Group?

#Get the Group by DisplayName $Group = Get-SCOMGroup -DisplayName "Windows Server 2016 and above Computer Group" #Get Members of the group $Instances = $Group | Get-SCOMClassInstance #Loop through each instance of the class FOREACH ($Instance in $Instances) { $dataObject = $ScriptContext.CreateFromObject($Instance,"Id=Id,HealthState=HealthState,DisplayName=DisplayName",$null) # Add the data object to be displayed in the dashboard $ScriptContext.ReturnCollection.Add($dataObject) }

image

You can see above – I now have a filtered list of only members of the “Windows Server 2016 and above Computer Group

 

Dashboard of objects filtered by a Monitor Health State

Now – here is a useful example…..  What if I want to see a dashboard of objects, but ONLY objects that have a specific monitor that is unhealthy?

For example – I can make a dashboard of Health Service Watchers, but ONLY show the Watchers where the Health Service Heartbeat Failure monitor is critical?  This example lets you show any type of object, where a give single monitor is unhealthy.  You cannot easily do this using a simple State view.

# Get the monitor $Monitor = Get-SCOMMonitor -Name 'Microsoft.SystemCenter.HealthService.Heartbeat' # Get the class which is targeted by the monitor $MonitorTargetClass = Get-SCOMClass -Id $Monitor.Target.Id # Get all instances of the targeted class $Instances = Get-SCOMClassInstance -Class $MonitorTargetClass # Build the collection to use when searching for the monitor state $MonitorCollection = New-Object -TypeName 'System.Collections.Generic.List[Microsoft.EnterpriseManagement.Configuration.ManagementPackMonitor]' $MonitorCollection.Add($Monitor) #Loop through each instance of the targeted class FOREACH ($Instance in $Instances) { # Find the state of the monitor for this instance $MonitorHealthState = $Instance.GetMonitoringStates($MonitorCollection)[0] #Only output instance if critical monitor state IF ($MonitorHealthState.HealthState -eq "Error") { #This monitor state is critical. Add to the Object and Properties for display in dashboard $dataObject = $ScriptContext.CreateFromObject($Instance,"Id=Id,State=HealthState,DisplayName=DisplayName",$null) $LastModified = $MonitorHealthState.LastTimeModified $dataObject['LastModified'] = $LastModified # Add the data object to be displayed in the dashboard $ScriptContext.ReturnCollection.Add($dataObject) } }

image

 

I’ll continue adding examples to this post.  Next up – I plan to show Contextual Widgets, where selecting an object in one Widget will get additional data in the next Widget.

16 Comments

  1. Edwio

    Wow Kevin, Thanks for another Great Article, very much appreciated! if i may, is there any chance you will be able to share knowledge about how to create a custom template in SCOM? i.e. like the default management pack templates, under the authoring tab. as there isn’t any documentation available.

  2. david zemdegs

    When I first tried this on my Windows 10 box I got errors running the script. So just a pointer to those working in strict UAC environments – you have to start the console as an administrator for it to work

  3. James Bryant

    This is an excellent post. Very useful.
    One thing I would like to see is more detail about how the data structure works to locate the information you picked out. An example would be the Objects filtered by Monitor Health.

  4. Aleksei Degotkov

    One of really helpful dashboards for me is the dashboard with Windows Computers where I can see a reason for MMode, start date, end date and an engineer who put computers into MMode:

    [string]$SCOMClassName = ‘Windows Computer’
    $SCOMClass = Get-SCOMClass -DisplayName $SCOMClassName
    $SCOMClassInstance = Get-SCOMClassInstance -Class $SCOMClass | Where-Object {$_.InMaintenanceMode -eq $true}
    $MMs = Get-SCOMMaintenanceMode -Instance $SCOMClassInstance
    Foreach ($MM in $MMs) {
    $dataObject = $ScriptContext.CreateInstance(“xsd://foo!bar/baz”)
    $dataObject[“Id”] = ($SCOMClassInstance | Where-Object ID -EQ $MM.MonitoringObjectId).DisplayName+’.’+$MM.MonitoringObjectId.ToString()
    $dataObject[“Name”] = ($SCOMClassInstance | Where-Object ID -EQ $MM.MonitoringObjectId).DisplayName
    $dataObject[‘Health State’] = ($SCOMClassInstance | Where-Object ID -EQ $MM.MonitoringObjectId).HealthState
    $dataObject[‘Start Time’] = $MM.StartTime
    $dataObject[‘Scheduled End Time’] = $MM.ScheduledEndTime
    $dataObject[“User”] = $MM.User
    $dataObject[“Comments”] = $MM.Comments
    $dataObject[“Reason”] = $MM.Reason
    $ScriptContext.ReturnCollection.Add($dataObject)
    }

  5. Graham Davies

    Just be careful with the code in “Dashboard of all Windows Computers in SCOM” – a windows computer that is greyed out in the SCOM Console – All Windows Computers View will still be listed with a green health state (health state = success) in the Widget \ dashboard if the server was healthy when it went down \ greyed out.

    If you run this, you’ll see that HealthState still shows as success (green in widget) even though IsAvailable is false.
    Get-SCOMClassInstance -Class $Class | Select DisplayName, HealthState, IsAvailable

  6. Charles

    Hi Kevin,

    Did you get a chance to make blog about a Contextual Widgets, where selecting an object in one Widget will get additional data in the next Widget?

  7. Charles

    Hi Kevin,

    On the native SCOM 2019 console dashboard, is there a widget that displays text or a counter? Something like a card or a tile that shows information about the total or a summary card. I’m interested in using the PowerShell widget to perform calculations and display that information in a text box, rather than presenting it in a table.

    I’ve seen this on DataCenter template dashboard for SQL Server. Could you guide me or provide a hint on how to develop my own custom dashboard? Unfortunately, we do not have a SCOM HTML5 web console in our environment.

  8. jake

    Hi Kevin/Guys — i checked and used this script to reflect for CPU, memory, resource utilizations bust seems its not reflecting values. Can you advise what’s missing?

    $class = Get-SCOMClass -Name Microsoft.Windows.Computer
    $computers = Get-SCOMClassInstance -Class $class
    $i=1
    foreach ($computer in $computers)
    {
    $cpu_usage = (Get-WmiObject -ComputerName $computer -Class win32_processor | Measure-Object -Property LoadPercentage -Average | Select-Object Average).Average.ToString()
    $mem_usage = Get-WmiObject win32_operatingsystem -ComputerName $computer | Foreach {“{0:N2}” -f ((($_.TotalVisibleMemorySize – $_.FreePhysicalMemory)*100)/ $_.TotalVisibleMemorySize)}
    $disk_usage_c = Get-WmiObject Win32_Volume -ComputerName $computer -Filter “DriveLetter = ‘C:'” | Foreach {“{0:N2}” -f (($_.FreeSpace / $_.Capacity)*100)}
    $disk_usage_d = Get-WmiObject Win32_Volume -ComputerName $computer -Filter “DriveLetter = ‘D:'” | Foreach {“{0:N2}” -f (($_.FreeSpace / $_.Capacity)*100)}
    $dataObject=$ScriptContext.CreateFromObject($computer,”Id=Id,HealthState=HealthState,DisplayName=DisplayName”,$null)
    $dataObject[“Index”]=$i
    $dataObject[“CPU%”]=$cpu_usage
    $dataObject[“Memory%”]=$mem_usage
    $dataObject[“C:Drive”]=$disk_usage_c
    $dataObject[“D:Drive”]=$disk_usage_d
    $ScriptContext.ReturnCollection.Add($dataObject)
    $i++
    }

Leave a Reply

Your email address will not be published.