From time to time, it is nice to take advantage of the agent and console tasks exposed in the SCOM console to more easily accomplish some sort of remediation or to retrieve some information. I have authored agent tasks before, and they are pretty straight forward. I do not believe I have ever authored a console task, however, when I received the request from one of my peers, I figured it would be a snap. The ask was to be able to execute a PowerShell script against the SDK straight out of the console and display the results back to the user. It ends up this is not too bad, but you do have to do some digging in order to see how these tasks are actually constructed.
Step one for me is to always try and find an example that I can reference. A quick Bing search did not turn up much, so I exported all of the MPs from my SCOM environment via PS and then scanned them for console tasks. I found an interesting one in the Microsoft.Windows.Server.Library management pack.
<ConsoleTask ID=”Microsoft.Windows.Server.Computer.OpenPowerShell” Accessibility=”Public” Enabled=”true” Target=”Windows!Microsoft.Windows.Server.Computer” RequireOutput=”false”>
<Assembly>Res.Microsoft.Windows.Server.Computer.OpenPowerShell</Assembly>
<Handler>ShellHandler</Handler>
<Parameters>
<Argument Name=”WorkingDirectory” />
<Argument Name=”Application”>powershell.exe </Argument>
<Argument> -noexit -command “Enter-PSSession -computer $Target/Property[Type=”Windows!Microsoft.Windows.Computer”]/PrincipalName$”</Argument>
</Parameters>
</ConsoleTask>
A straight forward task that simply opens PowerShell and creates a remote session on the targeted Windows Server Computer. This is essentially what I want to do, except I want to execute code against the SDK and display results rather than simply opening a remote session.
This is great. I did notice the <Assembly> line (highlighted in yellow above) that seems to basically define the type of task you are trying to execute. Searching the code further for this particular assembly, I find a resource at the very bottom of the management pack:
<Resources>
…
<Assembly ID=”Res.Microsoft.Windows.Server.Computer.OpenPowerShell” Accessibility=”Public” FileName=”Microsoft.Windows.Server.Computer.OpenPowerShell” HasNullStream=”true” QualifiedName=”Microsoft.Windows.Server.Computer.OpenPowerShell” />
</Resources>
I scoured my workstation, my MS servers, and the installation media for this file and I was not able to find it. I really want to track this down since this will potentially expose other types of console task types. My best guess is that this code has been relocated into some other DLL but I do not know for sure. If I find the code, I will post an update.
With that, I felt I had most of the necessary pieces in order to get an example running. For this example, I just wanted to do something simple like list all of the properties for a selected Windows Computer. Here is the script to do the work:
Param([String]$computerFQDN)
$key = ‘HKCU:Software\Microsoft\Microsoft Operations Manager\3.0\User Settings’
$SDK = (Get-ItemProperty -Path $key -Name SDKServiceMachine).SdkServiceMachineImport-Module OperationsManager
New-SCOMManagementGroupConnection $SDK## Get Windows Computer class
$computerClass = Get-SCOMClass -Name “Microsoft.Windows.Computer”## Get SCOM object
$computer = Get-SCOMClassInstance -Class $computerClass | Where-Object {($_.FullName -eq $computerFQDN) -or ($_.Name -eq $computerFQDN)}
$computer | fl *
This code connects to the SDK using whatever SDK service the machine upon which the script is being executed last connected. If multiple consoles are open and connected to multiple management groups, this approach will only work for Computer objects in the last console opened. However, this is fine for demo purposes and my lab since I only have a single environment.
Since the OpenPowershell module opens PowerShell and executes a scriptblock, I need to wrap the code above in a scriptblock and pass in the $computerFQDN value using a $Target variable:
<Parameters>
<Argument Name=”WorkingDirectory” />
<Argument Name=”Application”>powershell.exe </Argument>
<Argument><![CDATA[ -noexit -command “& {Param([String]$computerFQDN)
…
}” ]]></Argument>
<Argument>$Target/Property[Type=”Windows!Microsoft.Windows.Computer”]/PrincipalName$</Argument>
</Parameters>
Dropping this into a <ConsoleTask> and adding the exact code chunk to add the Assembly from the bottom of the Microsoft.Windows.Server.Library management pack yields the following:
When I click on my “Console Task – Get Computer Info” task, it launches the script which returns the following:
There are all of the properties for the selected Windows Computer. Results!