Welcome to MSDN Blogs Sign in | Join | Help

There have been a few questions regarding how to enumerate the rules targeting a class.

Here is a script you can save as a file. I named the script get-rulesforclass.ps1

param ([String] $className)

$class = get-monitoringclass | where {$_.Name -eq $className}

if ($class -eq $null)
{
 throw "Class '$className' not found.";
}

if ($class -is [Array])
{
 throw "More than one class was found with name '$className'.";
}

write-host $class

get-rule | where {$_.Target.Id -eq $class.Id}

Pass the name of the class to the script.

get-rulesforclass.ps1 Microsoft.Windows.Computer

The Target property of the rule is where most people get stuck because it is not clear that you must refer to the Id property off of the target property to perform the comparison against the class's Id.

This is the final blog post to the System Center Operations Manager Command Shell blog. I will be changing my focus and no longer have time to properly contribute to this blog. As this is the last post I will not longer be taking questions or comments. I wish you all the best of luck in your scripting endeavors.

Sayonara! 

Roger Sprague

I consistently get asked how to display class specific properties. The solution is simple but not very obvious.

get-monitoringobject ... | format-list * 

You are probably wondering why you even need to do this.

You are not alone:) 

Each MonitoringObject can be an instance of multiple classes so there is no limit on the number of enumerable properties on each MonitoringObject. To control the formatting experience we only display properties that are essential to identifying the instance you want to manage. To see the remaining properties you must override the default formatter by calling format-list or format-table. When attempting to format an object which has four or more variable length properties I find that format-list works best. Let's take a closer look at displaying all of the properties for each instance of Microsoft.Windows.Computer.

$class = get-monitoringclass | where {$_.Name -eq "Microsoft.Windows.Computer"}

get-monitoringobject -MonitoringClass: $class | format-list *

BTW this approach also works with objects returned by the OperationsManagerMonitoring provider.

PS Monitoring:\localhost

>dir | format-list *

And in case you aren't already aware 'fl' is the alias for format-list so the following command will work as well.

dir | fl *

 

Hope that helps and as always please post your questions and comments and I will make sure they are addressed in future posts.

Roger Sprague

A few of you sent mail asking how to delete an agent using the Command Shell. There is a Cmdlet for uninstalling an agent called Uninstall-Agent. However, uninstalling an agent will not work if the computer the agent is hosted by is not available. To help address the issue I created a function to automate the process. Keep in mind this function should only be used to delete an agent hosted by a computer that no longer exists otherwise you should use Uninstall-Agent. 

# Summary
#     Delete an agent hosted by a non-existent computer.
# Params
#     AgentNames - An array of strings that contain the FQDN of agents to delete.
# Returns
#     None
function global:Delete-Agent([System.String[]] $agentNames)
{
 $NoAgentsErrorMsg = "`nNo agent names specified. Please specify the FQDN for each agent you want to delete.`n";


 if ($agentNames -eq $null)
 {
  Write-Host $NoAgentsErrorMsg;
  return;
 }

 $administration = (get-item .).ManagementGroup.GetAdministration();

 $agentManagedComputerType = [Microsoft.EnterpriseManagement.Administration.AgentManagedComputer];

 $genericListType = [System.Collections.Generic.List``1]
 $genericList = $genericListType.MakeGenericType($agentManagedComputerType)

 $agentList = new-object $genericList.FullName

 foreach ($agentName in $agentNames)
 {
  $agent = Get-Agent | where {$_.PrincipalName -eq $agentName}
  
  if ($agent -eq $null)
  {
   $msg =  "Agent '{0}' not found." -f $agentName;  
   Write-Host $msg;

  }
  else
  {
   $agentList.Add($agent);
  } 
 }

 if ($agentList.Count -eq 0)
 {
  Write-Host $NoAgentsErrorMsg;
  return;
 }

 $genericReadOnlyCollectionType = [System.Collections.ObjectModel.ReadOnlyCollection``1]
 $genericReadOnlyCollection = $genericReadOnlyCollectionType.MakeGenericType($agentManagedComputerType)

 $agentReadOnlyCollection = new-object $genericReadOnlyCollection.FullName @(,$agentList);


 $msg = "`nDeleting {0} agents:`n" -f $agentReadOnlyCollection.Count;
 Write-Host $msg;
 foreach ($agent in $agentReadOnlyCollection)
 {
  Write-Host $agent.PrincipalName;
 }
 
 $administration.DeleteAgentManagedComputers($agentReadOnlyCollection);
}
 

Hope that helps and as always please post your questions and comments and I will make sure they are addressed in future posts.

Roger Sprague

Right before MMS 2007 I finished a video to help introduce folks to the Command Shell.

Here's a link.              

         http://www.microsoft.com/winme/0703/28666/Command_Shell_Intro_Edited.asx

Let me know if you want more videos. 

As always post your questions and comments.

Roger Sprague

 

Much like the Operations Manager UI Console the Command Shell offers several ways to discover Windows computers. You can either search by computer name or search by LDAP query. Let start by looking at the diferences between each approach.

 

The following command defines a LDAP query and passes it to the New-WindowsDiscoveryConfiguration Cmdlet thereby creating an LDAP based WindowsDiscoveryConfiguration.

$query = New-LdapQueryDiscoveryCriteria –LdapQuery: “(sAMAccountType=805306369)(name=srv1.contoso.com*)” –Domain:”contoso.com”

$discoConfig = New-WindowsDiscoveryConfiguration –LdapQueryDiscoveryCriteria:$query

In contrast the following command defines a name based WindowsDiscoveryConfiguration that will direct discovery to find both srv1.contoso.com and srv2.contoso.com.

$discoConfig = New-WindowsDiscoveryConfiguration  -ComputerName: "srv1.contoso.com", "srv2.contoso.com"

There is a lot more you can specify when defining a WindowsDiscoveryConfiguration. The following commands will direct the discovery module to use specific credentials, perform verification of each discovered Windows computer and constrain the type of discovered object to a Windows server. The ComputerType parameter is an enum that can be one of Workstation, Server, or Both. The PerformVerification switch is used to direct the discovery module to verify that only available computers should be returned.

# Prompt for credentials used to perform the discovery.

$creds = Get-Credential

# Define a WindowsDiscoveryConfiguration

$discoConfig = New-WindowsDiscoveryConfiguration –ComputerName: "srv3.contoso.com", "srv4.contoso.com" –PerformVerification: $true –ActionAccount:$creds -ComputerType: "Server"

# Select the Management Server used to run the discovery.

$managementServer = Get-ManagementServer –Root: $true

# Start the discovery process.

$discoResult = Start-Discovery –ManagementServer: $managementServer –WindowsDiscoveryConfiguration: $discoConfig

# Check that the discovery process discovered the Windows computers you specified.

$discoResult.CustomMonitoringObjects

# Last but not least install agents on the discovered computers.

Install-Agent –ManagementServer: $managementServer –AgentManagedComputer: $discoResult.CustomMonitoringObjects

Hope that helps and as always please post your questions and comments and I will make sure they are addressed in future posts.

Roger Sprague

You can run a task from the Command Shell much like you would from the UI Console. You start by selecting the object you want to work with then you select the task you want to run. In this scenario we are going to look at resetting the Health Service store of a hypothetical agent named echo12.contoso.com.

 

Like most blog posts all of the examples are based on working directly from the Root Management Server with a connection defined to localhost. If that is not how you are working simply replace 'localhost' with the name of your connection in the examples.

Monitoring:\localhost

>

 

Let's start by moving to the location of the Health Service of the computer we want to manage. If you are not sure just list all of the items under Microsoft.SystemCenter.AllComputersGroup by using 'dir' or the 'Get-ChildItem' command

# Move to the AllComputersGroup.

cd Microsoft.SystemCenter.AllComputersGroup

# List all of the member names of the AllComputersGroup

dir | Format-List PathName

# Move to the location of one of the members of the All Computers Group.

cd echo12.contoso.com

# Move to the location of the Health Service running on your agent.

cd Microsoft.SystemCenter.HealthService

 

Your prompt should look similar to the following. Much like all of the other Monitoring Object centric Cmdlets both Get-Task and Start-Task use the path as a context from which to work.

Monitoring:\localhost\Microsoft.SystemCenter.AllComputersGroup\echo12.contoso.com\Microsoft.SystemCenter.HealthService

>

Now let's get all the tasks for the current Health Service instance.

Get-Task | Format-List Name

We only care about resetting the Health Service store. We need to filter the results so that only the 'ResetHealthServiceStore' task is returned.

Get-Task | where {$_.Name -eq "Microsoft.SystemCenter.ResetHealthServiceStore"}

Once you have verified that your filter is working you can start the task.

Get-Task | where {$_.Name -eq "Microsoft.SystemCenter.ResetHealthServiceStore"} | Start-Task

Optionally you could create a variable to hold the task you want to start.

$task = Get-Task | where {$_.Name -eq "Microsoft.SystemCenter.ResetHealthServiceStore"}

Start-Task -Task: $task

The Start-Task Cmdlet will block until the task it is complete. If that is not the desired behavior specify the Asynchronous switch.

Start-Task -Task: $task -Asynchronous

If you want to see the status of your task a later time you can store the Task Result and use it to query for status updates.

$taskResult = Start-Task -Task: $task -Asynchronous

Get-TaskResult $taskResult.Id

If the task requires credentials you must first enter your credentials and store them in a variable.

$creds = Get-Credential

Start-Task -Task: $task -Credential: $creds

 

Last but not least you can specify overrides for existing properties of a task. I recommend specifying overrides by defining a variable so that you can verify your work before submitting the task. The following example is fictitious and is only used to illustrate how you would define overrides for a task.

$overrides = @{SignatureID=10; AnotherID="1092834098123407953912837"}

Start-Task -Task: $task -Override: $overrides

If you are not sure which overrides are available for a given task you can use the Get-Overrides Cmdlet. The following example lists the overrides for the task stored in the $task variable.

$task | Get-Override 

Hope that helps and as always please post your questions and comments and I will make sure they are addressed in future posts.

Roger Sprague

If you are not familiar with MCF in MOM 2005 you can read more about it here. I do not go into detail about MCF here as that is an area best covered by Jakub. What I do want to show you is how to setup MCF over tiering using the Operations Manager Command Shell. I encourage you to look at how to setup tiering before continuing on with this post.

 

MCF over tiering is a bit different than normal tiering in that you must define a run-as account used  by the Connector to connect to the tiered Management Group. Let's start by creating a run-as account used to connect to the Management Group you would like to tier. There is no Cmdlet for creating a run-as account so we must use PowerShell script to make Operations Manager SDK calls.

 

$runAsAccount = New-Object Microsoft.EnterpriseManagement.Monitoring.Security.MonitoringWindowsCredentialSecureData;

# Use Get-Credential to get a password in the form of a SecureString type.
$tierCreds = Get-Credential;

# Assumes the user name is in format "domain\user".
$domain,$userName, $junk = $tierCreds.UserName.Split("\");
$runAsAccount.Name = "My Tiered MCF Run-As Account"; # The name for this run-as account.
$runAsAccount.UserName = $userName;
$runAsAccount.Domain = $domain;
$runAsAccount.SecureData = $tierCreds.Password;

$mg = (Get-Item .).ManagementGroup; # Get a reference to the SDK Management Group object.
$mg.InsertMonitoringSecureData($runAsAccount); # Insert the run-as account.

That's that was a bit verbose. Just to make sure everything worked as expected run the following command and verify your new run-as account exists.

Get-RunAsAccount | fl Name

Next we need to create a tier.

# Get the credentials required to connect to the tiered Management Group.
$creds = Get-Credential ;

# Create the tier.
$tier = New-Tier -Name: "MyMcfTier" -ManagementServerName: "server2" -Credential: $creds -RunAsAccount: $runAsAccount;

Make sure your tier exists.

Get-Tier | fl Name

Next we need to create the Connector. There is no Cmdlet for creating a Connector so we must use PowerShell script to make Operations Manager SDK calls.

$connectorInfo = New-Object Microsoft.EnterpriseManagement.ConnectorFramework.ConnectorInfo;
$connectorInfo.Name = "McfOverTieringConnector";
$connectorInfo.Description = "McfOverTieringConnector Description"
$connectorInfo.DiscoveryDataIsManaged = $false;
$connector = $mg.GetConnectorFrameworkAdministration().Setup($connectorInfo);

Make sure your connector exists.

Get-Connector | fl Name

Last but not least we need to add the connector to the tier.

Add-ConnectorToTier -Tier: $tier -Connector: $connector;

Clearly the Command Shell could benefit from a New-RunAsAccount Cmdlet and a New-Connector Cmdlet to simplify this process. In the mean time I recommend you create functions that encapsulate any process that can't be completed using Cmdlets if you must complete the process multiple times.

If you happen to have multiple management groups and you need a way of seeing alerts aggregated across all of your Management Groups or you need a way of managing one Management Group via another (proxy) Management Group then tierring is just the ticket. The Operations Manager Command Shell provides explicit support for creating tiers and connecting to tiers. 

 

Start by connecting to the Management Group you want to make your top most tier and run the following commands.

$mgName = "The name for the tier you are creating.";

$msName = "The name of your Root Management Server of the Management Group you would like to tier";

$creds = Get-Credential; # The credentials needed to connect to the Management Group you would like to tier.

$tier = New-Tier -Name: $mgName -ManagementServerName: $msName -Credentials: $creds;

 

That's fairly easy and can be done without using variables. Here is a hypothetical example.

$creds = Get-Credential;

New-Tier -Name: Building10 -ManagementServerName: building10 -Credentials: $creds

 

Now that you have created the tier you need to verify that it works.

Start by creating a connection to the tier you just created.

$creds = Get-Credential; # The credentials need to connect to the tiered Management Group.

Get-Tier | where {$_.Name -eq "Building10"} | New-ManagementGroupConnection

cd \ # Move to the root of the provider as that is where you will discover all available connections.

dir # List all connections to find the connection you just created.

cd localhost.building10 # Set the location to the connection you just created. 

Notice that the tiered connection contains the host name of the Root Management Server from which the tier was acquired to help disambiguate a tiered connection from a direct connection to the same Management Group.

 

You can treat a tiered connection just like any other connection to a Management Group. Keep in mind the data is traveling through the Management Group from which the tier was acquired therefore most operations will be significantly slower than working directly with the Management Group. Some operations can be performed across multiple connections. Take a look at One Provider To Rule Them All! for more info on working with multiple connections.

Along with a healthy dose of Cmdlets, the Operations Manager snapin (aka "Command Shell") includes a PowerShell Provider that allows you to manage one or more Management Groups at the same time. 

To start, create a connection to each Management Group you want to manage. For example...

# Connect directly to a Management Group

New-ManagementGroupConnection mg1.redmond.corp.microsoft.com

or

# Connect to a Management Group that is a child tier of the current Management Group.

$creds = Get-Credential

Get-Tier | where {...} | New-ManagementGroupConnection -Credential:$creds

Next, move to the root of the Monitoring drive so you can see the connections you have created.

Monitoring:\...\> cd \

Monitoring:\> dir

That's it!

>>All operations from the root of the Monitoring drive will affect all connected Management Groups.<<

 

In case you are wondering how useful this is here are a few examples.

1. Find a Monitoring Object across all of your Management Groups.

dir -R | where {$_.Name -match "foobar"}

2. Install a management pack across all connected Management Groups.

Install-ManagementPack C:\ManagementPacks\CustomMP.xml

3. Get alerts across all connected Management Groups

Get-Alert ...

4. Get events across all connected Management Groups.

Get-Event ...

and so on...

 

Most GET Cmdlets work the same way even though they are spanning multiple connections. Cmdlets that affect change may not work as expected and will usually fail because they are passed an object that is unique to one Management Group.

BE CAREFUL!  Objects like ManagementPacks, Classes and Relationship Classes which are unique within one Management Group have the same identifier across all Management Groups and therefore can be inadvertently manipulated across multiple Management Groups when multiple connections exist.

BE VERY CAREFUL! More than one connection to the same Management Group can be created with a different name making it is very easy to inadvertently run the same command against the same Management Group multiple times.

Adding the Operations Manager Snapin

As you may already know, the PowerShell is an extensible environment, as such we have tried to create a useful starting point for you by loading the Operations Manager Cmdlets and functions within a PowerShell environment named “Command Shell”. For those of you who need to customize the PowerShell experience the "Command Shell" may not meet your needs. If you want access to Operations Manager Cmdlets from any PowerShell instance you must first load the Operations Manager snapin. Here is an example.

Add-PSSnapin Microsoft.EnterpriseManagement.OperationsManager.Client

Before you can start using the Operations Manager Cmdlets you must set the location to the root of the Operations Manager snapin. There are several ways of working with a provider. I recommend you create a drive so you can easily work with multiple Operations Manager connections.

# Set the location to the root of the provider namespace.

cd OperationsManagerMonitoring::

 

# or

# Create a drive that maps to the root of the provider namespace.

New-PSDrive -Name: Monitoring -PSProvider: OperationsManagerMonitoring -Root: \

cd Monitoring:\

Now that you are working with the correct provider you can create a connection to the Management Group you intend to manage.

# Replace 'localhost' with the name of your server if connecting remotely.

New-ManagementGroupConnection localhost 

cd localhost

Creating A Console File

That was fairly easy but what if you want to automate these commands every time you start the PowerShell. That requires adding a startup script and/or a console file. I suggest creating a console file to begin with to make the management of snapins easier.

Start by creating a copy of the PowerShell shortcut. 

Create a new console file by launching the new shortcut and running the following commands.

Add-PSSnapin Microsoft.EnterpriseManagement.OperationsManager.Client

Export-Console $home\myconsole

Close the PowerShell instance and open the properties of the new shortcut. Add the following as a parameter to powershell.exe in the Target field.

-PSConsoleFile myconsole.psc1

Adding A Startup Script

Now launch the new PowerShell shortcut. You may notice that the Operations Manager startup banner is missing as well as the default connection and all of the Operations Manager functions. The startup banner and functions can also be included in the startup of your custom PowerShell instance by creating a startup script.

Start by creating a file called mystartup.ps1 located in $home from within PowerShell. Add the following lines to the startup script to move to the Operations Manager installation directory.

$pf = (gc Env:\ProgramFiles)

cd "$pf\System Center Operations Manager 2007"

To add ONLY the Operations Manager functions add the following line to your script. If you decide to go this route you should also consider adding commands to connect to the Management Group you itend to manage.

.\Microsoft.EnterpriseManagement.OperationsManager.ClientShell.Functions.ps1

To add the Operations Manager functions, the default connection and the startup banner add the following line to your startup script. I suggest using this approach until you are familiar with Operations Manager connection Cmdlets.

.\Microsoft.EnterpriseManagement.OperationsManager.ClientShell.Startup.ps1

Now you need to call the startup script from your PowerShell shortcut. Open the shortcut properties and add the following arguments at the end of the Target field.

-NoExit .\mystartup.ps1

That’s it! Now you can fully customize your powershell startup experiance while still having immediate access to Operations Manager functionality.

DateTime property values off of objects returned from the Operations Manager (OM) SDK are in UTC time. At the time of this writing the "Kind" property of these values is not populated. This may seem trivial or irrelevant but it raises some questions as to how Cmdlets designed to take DateTime values should treat values that do not specify the "Kind" property. Consider the following example.

Monitoring:\localhost\Microsoft.SystemCenter.AllComputersGroup
>$time = [DateTime]::Now

>$time
Monday, November 27, 2006 6:35:10 PM

>$time.Kind
Local

>New-MaintenanceWindow -startTime: ($time) -endTime: ($time.AddDays(1)) -reason: "ApplicationInstallation" -comment: "Testing DateTime.Now";

>Monitoring:localhost\>Get-MaintenanceWindow MonitoringObjectId : 3c8ac4f3-475e-44dd-4163-8a97af363705

StartTime : 11/28/2006 2:35:12 AM
ScheduledEndTime : 11/29/2006 2:35:12 AM
EndTime
Reason : ApplicationInstallation
Comments : testing DateTime.Now
User : SMX\asttest
LastModified : 11/28/2006 2:35:12 AM
ManagementGroup : rogers01dmg
ManagementGroupId : 4e2f3ced-4b50-3939-edac-b9dfabe5effa

Clearly some conversion has occurred here. The value from [DateTime]::Now is in local time. The New-MaintenanceWindow Cmdlet converts the local time to UTC time before creating the maintenance window. All is good as the maintenance window will occur at the local time specified by the user. If you try the same example by specifying a string value for the DateTime parameters you get a different result. Consider the following example where the user is working in the PST time zone.

>[DateTime] $time = "11/28/2006"

>$time
Monday, November 28, 2006 12:00:00 AM

>$time.Kind
Unspecified

>New-MaintenanceWindow -startTime: $time -endTime: ($time.AddDays(1)) -reason: "ApplicationInstallation" -comment: "Testing DateTime string conversion"; >Monitoring:localhost\>Get-MaintenanceWindow
MonitoringObjectId : 3c8ac4f3-475e-44dd-4163-8a97af363705
StartTime : 11/28/2006 12:00:00 AM
ScheduledEndTime : 11/29/2006 12:00:00 AM
EndTime :
Reason : ApplicationInstallation
Comments : testing DateTime.Now
User : SMX\asttest
LastModified : 11/28/2006 2:40:00 AM
ManagementGroup : rogers01dmg
ManagementGroupId : 4e2f3ced-4b50-3939-edac-b9dfabe5effa

Great, the time value specified is the time value that is returned. All is good, or so it seems. There is a problem. The time is understood to be UTC time to the server that determines when the maintenance window starts and stops. In this case the maintenance window is going to start on 11/27/2006 at 2 PM PST. This is not what the user intended in this case. This same problem also occurs when using a DateTime value off of an SDK object to specify the parameter of type DateTime on the OM Cmdlets. If you are confused, try to remember the following guidelines.

  1. Always specify the DateTime.Kind property.
    • [DateTime]::Now and Get-Date specify the DateTime.Kind for you.
    • String conversion as in, "11/27/2006", does not specify the DateTime.Kind property.
    • Objects returned from the OM SDK do not specify the DateTime.Kind property.
  2. DateTime property values off of objects returned from the OM SDK are in UTC time.
  3. DateTime values passed as parameters to OM Cmdlets which do not specify the "Kind" property will be treated as UTC time.
  4. DateTime values passed as parameters to OM Cmdlets in local time will be converted to UTC time.

 

Overview. 1

Resources. 1

Starting the System Center Command Shell 2

Connecting To a Management Group. 2

Administration. 3

Agent Management 3

Computer Maintenance. 4

Default Settings. 4

User Roles. 4

Authoring. 5

Management Packs. 5

Rules. 5

Monitoring. 5

Navigation and Scoping. 5

Operational Data. 6

Managing Alerts. 7

 

Overview

This document is intended to help users familiar with PowerShell to start using the commands provided by the System Center Operations Manager Command Shell. This document looks at common scenarios and provides examples and tips for each scenario.

 

??? – Technical detail that is not necessary to continue reading but maybe useful.

 

!!! – Warning that the information must be read and followed as it pertains to the rest of the guide.

 

[ ] – A replacement parameter is required that you must specify.

 

 

Resources

This document barely scratches the surface of the functionality provided by Operations Manager Command Shell.  To learn more use the online help and the Get-Help command. To see all available Operations Manager commands use the Get-OperationsManagerCommand function.

 

If you need help getting started using the PowerShell read the “Getting Started Guide” included with PowerShell.

 

You find out more about PowerShell here…

 http://www.microsoft.com/windowsserver2003/technologies/management/powershell/default.mspx

 

You can download PowerShell from here…

 http://www.microsoft.com/windowsserver2003/technologies/management/powershell/download.mspx

 

 

!!! Please send your questions and comments to the SDK/Operations Manager Command Shell news group microsoft.beta.opsmgr.sdk.powershell available on betanews.microsoft.com.

 

Starting the System Center Command Shell

The System Center Command Shell is accessible from the System Center UI Console as well as the Start menu. Use the right-click context menu in the UI Console to launch a Operations Manager Command Shell that sets the location to the target object. Use the Start->Programs->System Center

 

!!! - The remainder of this document assumes that you have an open Operations Manager Command Shell.

 

??? -The Operations Manager Shell is merely an extension to Monad/PowerShell, called a snapin. The Operations Manager Command Shell snapin can be loaded by any instance of Monad/PowerShell. The Operations Manager snapin is named “Microsoft.EnterpriseManagement.OperationsManager.ClientShell”. Use Get-PSSnapin –Registered to list the registered snapins. Use Add-PSSnapin to add the Microsoft.EnterpriseManagement.Shell snapin to the current PowerShell instance.

 

Connecting To a Management Group

!!! - The following examples use a fictitious topology containing a Root Management Server with the name ‘computer1’ and computers with names ‘computer2’ and ‘computer3’ in a domain named ‘MyDomain’.

 

By default a connection to a Management Group is created when starting the Operations Manager Command Shell. Connections are made to the Root Management Server of a Management Group. The startup procedure of the Operations Manager Command Shell sets the current location to the root of the default connection.  This is also referred to as the root of the instance space. Here is an example of the Operations Manager Command Shell startup prompt.

 

PS Monitoring:\localhost>

 

In the rare case when you need to change the connection or connect to more than one Management Group you can use the New-ManagementGroupConnection Cmdlet. The New-ManagementGroupConnection Cmdlet can create a connection to the Root Management Server in a Management Group. Here is an example of using the New-ManagementGroupConnection Cmdlet.

 

PS Monitoring:\> New-ManagementGroupConnection

-ConnectionString: [Root Management Server Name]

 

 

Once you have created the connection you need to move to the root of the of that connection. Use Get-ChildItem to determine the names of the root items of the instance space.

Use Set-Location to move to the root of the connection. Here is an example…

 

Get-ChildItem

PathName             : localhost

ManagementGroup      : computer1

ManagementServerName : localhost

Drives               : {}

 

Set-Location localhost

 

 

??? - You can also use the cd alias and tab completion to select the connection. You can then use the dir alias to list items at the current location.

 

Administration       

Agent Management

 

After installing Operations Manager your first task is to discover and deploy agents on the computers you want to manage. The Operations Manager Command Shell provides you with  the ability to perform computer discovery as well as device discovery. Each agent computer must be targeted to at least one Management Server within a Management Group. Depending on your configuration you may have more than one Management Server therefore you must first decide which Management Server to which you would like the new agent computers to report. This can be done by calling Get-ManagementServer. Once you have decided which management server you want to use you must store it in a variable so that it can be passed to the Install-Agent command for deploying the agent to a computer. Let’s take a look at this in more script centric terms.

 

 

# Get the Root Management Server.

$managementServer = Get-ManagementServer -Root: $true

 

# Create the discovery configuration for computer2 and computer3.

$discoConfig = New-WindowsDiscoveryConfiguration

-ComputerName: computer2, computer3

 

# Discover the computers.

$discoResult = Start-Discovery

-ManagementServer: $managementServer

-WindowsDiscoveryConfiguration: $discoConfig

 

# Install an agent on each computer.

Install-Agent

-ManagementServer: $managementServer

-AgentManagedComputer: $discoResult.CustomMonitoringObjects

 

The first step is to get the desired management server. In this example the same management server will perform discovery, agent installation and will act as the Root Management Server for both agents.  The second step creates the discovery configuration used to define the type of discovery to perform. The third step starts discovery and blocks until it completes. The final step installs an agent on the discovered computers. This process is not for the faint of heart but can be easily automated with a PowerShell function or script.

 

Once the installation is complete a pending action is created for each agent. The pending action allows for a short period of time before the agent is added to Operations Manager. If you want to complete the process immediately you can approve the pending actions for computer1 and computer2 by using the Approve-AgentPendingAction command. If on the other hand you change you mind and you don’t want the computers to be managed then run the Reject-AgentPendingAction Cmdlet.

 

Get-AgentPendingAction | where {$_.AgentName –like ‘computer*’} |

Approve-AgentPendingAction

 

Once the pending actions are approved you can use the Get-Agent command to see that computer2, and computer3 are now managed. Prior to approving the pending action computer2 and computer3 may not be returned from the Get-Agent command.

 

If for some reason you no longer wish to manage a computer the agent can be uninstalled by running the Uninstall-Agent command.

 

 

Get-Agent | where {$_.RootName –like ‘computer*’ } |

Uninstall-Agent

 

 

 

Computer Maintenance

 

Once a computer is managed by Operations Manager, a maintenance window must be defined before taking the computer offline for maintenance otherwise alerts may be generated when the computer is offline. The Operations Manager Command Shell provides commands for getting and defining a maintenance window. Keep in mind that a maintenance window can be defined for entities hosted by a computer as well as the computer itself.  The following example illustrates the use of the New-MaintenanceWindow command.

 

$computer = Get-Agent | where {$_.Name -like ‘computer*’}

 

$computer.HostComputer | New-MaintenanceWindow  

-StartTime: ‘5/22/2006 00:30’

-EndTime: ‘5/22/2006 12:30’

-Comment: "Install security patch"

 

If the existing maintenance window needs to be modified use the Set-MaintenanceWindow command. You can not modify the start time for a maintenance window once it has been defined using the Command Shell. Use New-MaintenanceWindow to define an alternate maintenance window if the start time must be changed. Use Get-MaintenanceWindow to see the state of the current maintenance window. Use the InMaintenanceMode property to determine if an object is in maintenance mode.

 

$computer.HostComputer | Get-MaintenanceWindow

 

$computer.HostComputer | Set-MaintenanceWindow -EndTime: "5/24/2006 12:30"

 

 

Default Settings

All of the configurable default settings used by Operations Manager are configurable using the Command Shell. Use Get-DefaultSetting and Set-DefaultSetting to manage default settings such as the Agent Heartbeat Interval.

 

Set-DefaultSetting -Name: Agent\Heartbeats\Interval -Value: 50

Get-DefaultSetting | where {$_.Name –eq ‘Agent\Heartbeats\Interval’}

 

 

User Roles

 

User roles are an integral mechanism for managing access to Operations Manager functionality in a role based fashion. To see the available user roles use the Get-UserRole command. Here is an example of adding a user named ‘tomg’ to the Operations Manager Operators user role.

 

$userRole = Get-UserRole |

where {$_.Name –eq ‘OperationsManagerReadOnlyOperators’}

 

$userRole.Users.Add(‘tomg’)

 

$userRole.Update()

 

 

The following example searches for all user roles in which ‘tomg’ is a member.

 

Get-UserRole | where {$_.Users –match ‘tomg’}

 

 

Authoring

 

Management Packs

The monitoring extensibility of Operations Manager is built on Management Packs which can be installed, uninstalled and exported. The following example demonstrates commands for managing Management Packs.

 

$myMPs = Get-ManagementPack | where {$_.Name –match “MyMP”}

 

Install-ManagementPack –FilePath: c:\MyMP.xml

 

Get-ManagementPack | where {$_.Name –match “MyMP”} |

Uninstall-ManagementPack

 

Management Packs can be exported and then installed on another Management Group. This feature is useful if you use a staging server to test Management Pack changes. Use Export-ManagementPack and specify the directory into which you want to the Management Pack exported.

 

Get-ManagementPack | where {$_.Name –match “MyMP”} |

Export-ManagementPack –Path: “c:\MyMPs”

 

 

Rules

It is sometimes useful to disable a rule when planned changes occur to a topology or application in which Monitoring Objects of the same Monitoring Class are affected. Use Enable-Rule and Disable-Rule for managing rules that are NOT contained in a sealed Management Pack. Use Get-Rule for finding rules in any installed Management Pack.

 

Get-Rule | where {$_.Name –match “MyRule”} | Disable-Rule

 

Get-Rule | where {$_.Name –match “MyRule”} | Enable-Rule

 

 

Monitoring

 

Navigation and Scoping

SC Operations Manager uses an abstraction called a MonitoringObject that allows applications and services as well as computers to be similarly modeled for both monitoring and management purposes. The Command Shell heavily utilizes the MonitoringObject abstraction and its type object, MonitoringClass, to allow you to retrieve and filter monitoring and management information.

 

By default the Operations Manager Command Shell sets the current PowerShell provider to the OperationsManagerMonitoring provider which displays the location of the MonitoringObject membership relationship space starting with a connection to a Root Management Server. Here is an example where ‘computer1’ represents the name of a Root Management Server.

 

PS Monitoring:\computer1>

 

In addition to computers, services and applications a MonitoringObject can represent a logical group within Operations Manager. Use the intrinsic Get-ChildItem command to list the root Monitoring Objects within a connection. Much like the PowerShell’s File System provider the OpsMgr provider is hierarchical, therefore most of the read commands used with the File System provider also work with the OpsMgr provider.

 

PS Monitoring:\computer1>Get-ChildItem

 

 

In addition to the intrinsic provider commands of the PowerShell most of the Operations Manager Command Shell commands are aware of the current location of the OpsMgr provider. Moreover all of the Operations Manager Command Shell commands that are aware of the current OpsMgr provider location can work from the root of the provider path thereby allowing you to run commands across multiple connections. The following example gets all of the top level MonitoringObjects across all available connections to a Root Management Server.

 

PS Monitoring:\>Get-ChildItem

 

!!! Be careful. There is no ‘undo’ feature in the PowerShell therefore any commands that affect change should be used with extreme caution especially when run from the root of the OpsMgr provider.

 

Just as moving to the root of the path increases the scope of a command, moving down the path to a specific MonitoringObject decreases the scope of the command. The following command gets the alerts for a specific Monitoring Group.

 

PS Monitoring:\localhost\Microsoft.SystemCenter.AllComputersGroup>Get-Alert

 

??? Use the cd alias and tab completion to quickly change the provider location.

 

In addition to the OpsMgr provider the Operations Manager Command Shell also includes the Get-MonitoringObject command that allows you to find a MonitoringObject by MonitoringClass or by ID. Here we are getting all MonitoringObjects that contain the word ‘computer’ in the class name regardless of the group in which the MonitoringObject is contained.

 

PS Monitoring:\>Get-MonitoringClass | where {$_.Name –match “computer” } |

Get-MonitoringObject

 

 

Operational Data

SC Operations Manager monitoring is primarily driven by operational data for each MonitoringObject such as events, state and performance data. Operational data can be retrieved for each MonitoringObject using the Operations Manager Command Shell. MonitoringObjects that represent a group or containment entity typically aggregate or coalesce the operational data for related MonitoringObjects. Here are a few examples use the operational data commands.

 

PS Monitoring:\localhost>Get-Alert | where {$_.Severity –eq “Critical”}

 

PS Monitoring:\localhost>Get-State

 

PS Monitoring:\localhost> Get-Event | where {$_.Number –gt 30000}

 

PS Monitoring:\localhost>Get-PerformanceCounter |

where {$_.Name –match “Processor Time”} |

Get-PerformanceCounterValue

–StartTime: “5/23/2006”

–EndTime: “5/24/2006”

 

PS Monitoring:\localhost>Get-Monitor

 

Managing Alerts

At some point while using Operations Manager you will see one or more Alerts for a Monitoring Object. In order to reset the state of the MonitoringObject the alert must be resolved. The Operations Manager Command Shell provides the Resolve-Alert command for resolving one or more alerts.  Here is an example.

 

PS Monitoring:\localhost> Get-Alert |

where {$_.ResolutionState –eq “New” –and $_.Owner –eq “me” } | Resolve-Alert “resolving all new alerts”