SCOM Powershell Grid Widget for Mere Mortals

Just 2 hours left before I’ll open the door and will head to Houston for TechEd North America 2014. Great time to write a short blog post about an awesome feature introduced with Update Rollup #2 for SCOM 2012 R2  – Powershell Grid Widget.

Where to find

Download and install Update Rollup #2 as described in this KB article. Don’t forget to import new management packs from %SystemDrive%\Program Files\Microsoft System Center 2012 R2\Operations Manager\Server\Management Packs for Update Rollups. One of the MPs will be Microsoft.SystemCenter.Visualization.Component.Library.mpb – it contains several hidden gems inside, one of them – Powershell Grid Widget.

PS Grid Widget Add Dialog

What’s that?

SCOM Powershell Grid Widget can be added to any SCOM Dashboards and takes PS script as configuration:

PS Grid Widget Script Setting

So, SCOM users are free to write their own scripts to collect data from any data source (not just SCOM) and have that data displayed in the SCOM console (both windows and web). And of course, these scripts can use SCOM cmdlets and SCOM SDK API to get information from SCOM itself.

Scripts for SCOM Powershell Grid Widget by example

Note: Please note my comments placed inside the code.

1. Hello World

Param($globalSelectedItems)

$dataObject = $ScriptContext.CreateInstance("xsd://olegkapustin.com/MySchema");
$dataObject["Id"]="1"; # Id should be string! String!! STRING !!!
$dataObject["First Name"]="Hello";
$dataObject["Last Name"]="World";
$ScriptContext.ReturnCollection.Add($dataObject);

Poweshell Grid Widget Hello World

2. ID should be unique

This will not work:

Param($globalSelectedItems)

$dataObjectA = $ScriptContext.CreateInstance("xsd://olegkapustin.com/MySchema");
$dataObjectA["Id"]="1"; 
$dataObjectA["First Name"]="Hello";
$dataObjectA["Last Name"]="World";
$ScriptContext.ReturnCollection.Add($dataObjectA);  

$dataObjectB = $ScriptContext.CreateInstance("xsd://olegkapustin.com/MySchema");
$dataObjectB["Id"]="1"; # This object will NOT be added due to duplicated IDs
$dataObjectB["First Name"]="Goodbye";
$dataObjectB["Last Name"]="World";

$ScriptContext.ReturnCollection.Add($dataObjectB);

This is correct:

Param($globalSelectedItems)

$dataObjectA = $ScriptContext.CreateInstance("xsd://olegkapustin.com/MySchema");
$dataObjectA["Id"]="1"; 
$dataObjectA["First Name"]="Hello";
$dataObjectA["Last Name"]="World";
$ScriptContext.ReturnCollection.Add($dataObjectA);  

$dataObjectB = $ScriptContext.CreateInstance("xsd://olegkapustin.com/MySchema");
$dataObjectB["Id"]="2"; # This object will be added - IDs are unique
$dataObjectB["First Name"]="Goodbye";
$dataObjectB["Last Name"]="World";

$ScriptContext.ReturnCollection.Add($dataObjectB);

Poweshell Grid Widget Hello World 2

3. Where does it run? Who am I? Can I write to disk?

Param($globalSelectedItems)

function debug($msg)
{
	#Can I write to disk? Absolutely!
	[string]::Format("{0} {1}",[datetime]::Now,$msg) | Out-File -FilePath C:\-Docs\PSGrid.txt -Append
}

$dataObject = $ScriptContext.CreateInstance("xsd://olegkapustin.com/schemas/PowerShellGridWidgetTest");
$dataObject["Id"]="1"; # Id should be string! String!! STRING !!!
$dataObject["Who?"]=[System.Security.Principal.WindowsIdentity]::GetCurrent().Name #Local You
$dataObject["Where?"]=[Environment]::MachineName; #Your local machine (surprise!)
$ScriptContext.ReturnCollection.Add($dataObject);  

debug("Hello Debug!")

4. Throwing exceptions

Param($globalSelectedItems)

throw "Hello World Not Found!"

SCOM Poweshell Grid Widget Exception

SCOM Poweshell Grid Widget Exception Details

5. Other widgets set the context

Now the one and only parameter comes to the stage:

#Hint #1: switch to another view and back to dashboard if you changed column names and/or order. 
#Hint #2: columns with null values will not be displayed
Param($globalSelectedItems)

$i = 0
foreach ($item in $globalSelectedItems)
{
	$dataObject = $ScriptContext.CreateInstance("xsd://olegkapustin.com/schemas/PowerShellGridWidgetTest");
	$dataObject["Id"]=$i.ToString();
	$dataObject["Object Id"]=$Item["Id"];
	$dataObject["Type"]=$Item.GetType().ToString();
	$ScriptContext.ReturnCollection.Add($dataObject);  
	++$i
}

Another way to explore the $globalSelectedItems parameter:

Param($globalSelectedItems)

$i = 0
foreach ($item in $globalSelectedItems)
{
	$item | Get-Member | Out-File -FilePath C:\-docs\psGrid_SelectedItem.txt
	$item.CollectionKeyProperty | Get-Member | Out-File -FilePath C:\-docs\psGrid_SelectedItem.txt -Append
	$item.CollectionKeyProperty | Out-File -FilePath C:\-docs\psGrid_SelectedItem.txt -Append # It has only Id 🙁
	break;
}

6. Getting related (hosted and contained) objects for the current context

Param($globalSelectedItems)

function debug($msg)
{
	#Can I write to disk? Absolutely!
	[string]::Format("{0} {1}",[datetime]::Now,$msg) | Out-File -FilePath C:\-Docs\PSGrid.txt -Append
}

foreach ($globalSelectedItem in $globalSelectedItems)
{
	$globalSelectedItemInstance = Get-SCOMClassInstance -Id $globalSelectedItem["Id"]
	foreach ($relatedItem in $globalSelectedItemInstance.GetRelatedMonitoringObjects())
	{
		debug($relatedItem.GetType().ToString())
		$dataObject = $ScriptContext.CreateFromObject($relatedItem, "Id=Id,State=HealthState,DisplayName=DisplayName,Path=Path", $null)
		$dataObject["ParentRelatedObject"] = $globalSelectedItemInstance.DisplayName
		$ScriptContext.ReturnCollection.Add($dataObject)
	}
}

SCOM PS Grid Widget In Action

Where to learn more?

Conclusion

The only thing I can write here is that I like this widget and hope to see more features like this. I like it so much, so I will use it in my demo during my DCIM-B415 session at TechEd. See you there!

8 thoughts on “SCOM Powershell Grid Widget for Mere Mortals

  1. Thanks for this great work!

    I love this new powershell grid widgets but there’s one thing…

    Is it possible to copy data out of a powershell grid widget or follow a hyperlink (currently it’s just plain text and not clickable…)? Or is there another workaround?

    My Powershell Grid Widget is generated this way:

    $dataObjectA = $ScriptContext.CreateInstance(“xsd://test-it/now”);
    $dataObjectA[“Id”]=”1″;
    $dataObjectA[“SysInfo”]=$output;
    $ScriptContext.ReturnCollection.Add($dataObjectA);

    In $output there’s e.g a hyperlink (and some other data) which is displayed correctly but not clickable or copyable.

    • I’d rather go for PS browser widget in this case. Something like:

      $file = $env:TEMP+'\'+[guid]::NewGuid().ToString()+'.html'

      $header = '<html><head><title></title></head><body><table><tr><th>Name</th><th>Link</th></tr>'
      $rowtemplate='<tr><td>{0}</td><td><a href="http://myhost.local/{1}">link</a></td></tr>'
      $footer = '</table></body><html>'

      $content=$header
      Get-SCOMClass -Name "Microsoft.Windows.Computer" | Get-SCOMMonitoringObject | %{
      $content+=($rowtemplate -f $_.DisplayName, $_.Id)
      }
      $content+=$footer

      $content > $file

      $dataObject = $ScriptContext.CreateInstance("xsd://Microsoft.SystemCenter.Visualization.Component.Library!Microsoft.SystemCenter.Visualization.Component.Library.WebBrowser.Schema/Request")
      $dataObject["BaseUrl"]="file:///$file"
      $ScriptContext.ReturnCollection.Add($dataObject)

  2. Hey Oleg, wondering if you’d know whether it is possible to create a column using the createinstance method, whose type is a healthstate icon, the same way you have when you createfromobject? I’ve been trying to do that in many different ways, with no luck.
    Thank you
    Jose

  3. Thank you for sharing this article!

    I’m inspired to this post for configure SCOM to get the result of the Get-CusterGroup in a Powershell Grid widget but I don’t understand how to configure the import-module function.
    I try to explain: The command returns the list of roles of my cluster, the ownernode (to know where is running the single resource), and the status (Online or Offline). It seems strange but with the MP of FailoverCluster I can’t do this because I can’t configure the OwnerNode in my view. So, I try to use this script in PS.
    The script works but only if the dashboard is viewed by PCs that have installed the Windows feature that add the tools of failovercluster. If I try to view the dashbord from a PC that don’t have this features installed, the window of scom appears empty.
    How can I add the module to integrate it into my script? I need this to display the dashboard without that I have to install the windows feature.
    Thanks,

    Antonio

    • Antonio, PS grid script runs on a client side, as far as I remember, thus, if you’re using some PS modules, you need them on the client. You may opt for using non-PS interfaces like WMI or such to avoid the use of modules or check if the required module installed.

      P.S.: sorry for the very delayed answer 🙂

Leave a Comment