Kevin Holman's System Center Blog

Posts in this blog are provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified in the Terms of UseAre you interested in having a dedicated engineer that will be your Mic

Using the agent scripting objects on a SCOM 2012 agent

Using the agent scripting objects on a SCOM 2012 agent

  • Comments 10
  • Likes

 

I previously wrote about the new agent control panel applet with SCOM 2012 here:

http://blogs.technet.com/b/kevinholman/archive/2011/11/10/opsmgr-2012-new-feature-the-agent-control-panel-applet.aspx

 

There will be times that we want to make changes to our agent configuration, and often times a script is the simplest way to do this on a large number of agents.  Perhaps we want to add an additional management group to the agent, or enable/disable Active directory integration? 

The most common scenario will be when multi-homing agents in a side by side SCOM 2007 to SCOM 2012 migration, to have an automated way to remove the old SCOM 2007 management group.

The agent configuration objects are documented here:  http://msdn.microsoft.com/en-us/library/hh328967.aspx

ManagementServiceConfigurationClass.AddManagementGroup
This method adds a new, but inactive, management group to the agent.
 
ManagementServiceConfigurationClass.DisableActiveDirectoryIntegration
This method prevents an agent from querying Active Directory or Active Directory Domain Services (AD DS) for the list of the management groups in which this agent participates.
 
ManagementServiceConfigurationClass.EnableActiveDirectoryIntegration
This method allows an agent to query Active Directory or AD DS for the list of the management groups in which this agent participates.
 
ManagementServiceConfigurationClass.GetActiveDirectoryIntegrationEnabled
This method returns a Boolean value indicating whether or not true Active Directory integration is enabled for the agent.
 
ManagementServiceConfigurationClass.GetManagementGroup
This method returns a ManagementServiceConfigurationClass Object object.
 
ManagementServiceConfigurationClass.GetManagementGroups
This method returns a ManagementGroupCollectionClass Object object.
 
ManagementServiceConfigurationClass.ReloadConfiguration
This method reloads the updated agent configuration.

ManagementServiceConfigurationClass.RemoveManagementGroup
This method removes an active management group from the agent.
 
ManagementServiceConfigurationClass.UpdateActionAccount
This method updates the existing action account for a given management group with the given account.
 

Here are some code examples that run in VBScript.  I choose VBscript because not all agent managed machines will have PowerShell installed (Server 2003, and 2008 by default).

Add a management group to an existing agent

Option Explicit Dim objMSConfig Set objMSConfig = CreateObject("AgentConfigManager.MgmtSvcCfg") ' Add a management group Call objMSConfig.AddManagementGroup ("ManagementGroupName", "ManagementServer.domain.com",5723)

Add a management group to an existing agent, and initiate a restart of the agent to immediately accept the changes

Option Explicit Dim objMSConfig Set objMSConfig = CreateObject("AgentConfigManager.MgmtSvcCfg") ' Add a management group Call objMSConfig.AddManagementGroup ("ManagementGroupName", "ManagementServer.domain.com",5723) Call objMSConfig.ReloadConfiguration

Remove a management group from an agent, and restart

Option Explicit Dim objMSConfig Set objMSConfig = CreateObject("AgentConfigManager.MgmtSvcCfg") ' Remove a management group Call objMSConfig.RemoveManagementGroup ("ManagementGroupName") Call objMSConfig.ReloadConfiguration

Disable AD Integration on an agent (then restart) which will delete all AD integrated management groups from the agent.

Option Explicit Dim objMSConfig Set objMSConfig = CreateObject("AgentConfigManager.MgmtSvcCfg") ' Disable AD Integration Call objMSConfig.DisableActiveDirectoryIntegration() Call objMSConfig.ReloadConfiguration

You can get pretty fancy with your scripts – to add error detection, if/then, to make a lot of actions in one push.  Here is an example written by Joe Thompson, from http://www.systemcentercentral.com/forums-archive/topic/deploying-scom-2012-agents-using-sccm-2012/

I will insert his code example directly here:

Option Explicit On Error Resume Next Dim objMSConfig, objMG, isChange isChange = 0 Set objMSConfig = CreateObject(“AgentConfigManager.MgmtSvcCfg”) If Err <> 0 Then wscript.echo “Agent not installed or extension error!” wscript.quit(Err) End if 'See if Mgmt Group exists Set objMG = objMSConfig.GetManagementGroup (“MYNEWMG”) If Err <> 0 Then ‘New Mgmt not set. ’Add a management group Call objMSConfig.AddManagementGroup (“MYNEWMG”, “mymanagementserver.contoso.com”,5723) objMSConfig.ReloadConfiguration isChange = isChange + 1 End If WSCript.Sleep 15000 ‘Remove a management group if it exists Set objMG = objMSConfig.GetManagementGroup (“MYOLDMG”) If Err = 0 Then Call objMSConfig.RemoveManagementGroup (“MYOLDMG”) objMSConfig.ReloadConfiguration isChange = isChange + 1 End If Wscript.Echo “Compliant” WScript.Quit

There are also good samples on how to make a SCOM task with a script like this – to add or remove management groups straight from your existing SCOM deployment:  http://scomandplus.blogspot.com/2012/07/adding-scom-agent-task-to-update.html

 

Wrapping it up in a management pack:

I am going to use all of this above – to create a management pack.  The purpose of this MP will be to discover which agents are multi-homed, and then provide an agent based task in the new management group – to remove the old management group.

I will start with a simple class and discovery, which will discover any healthservice that has an HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Agent Management Groups key. 

Next, I will create a monitor, that will look for the existence of a Registry Key, which I wrote about here:  http://blogs.technet.com/b/kevinholman/archive/2010/07/29/how-to-create-monitor-for-existence-of-a-registry-key.aspx  We can use this to detect the existence of the unwanted management group.

Last, we will create a task, and target it to our new class.

Here is the XML of the MP.  It is very simple… a class (based on Local Application) with a simple registry discovery that should discover all agents.  Then a monitor to inspect for your “old” management group.  Then a console task (which will show up when you look at the state view included) to remove the management group (this is hard coded to my test MG name, but you just need to edit the script to change it).

<ManagementPack ContentReadable="true" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <Manifest> <Identity> <ID>Example.SCOMMigration</ID> <Version>1.0.0.9</Version> </Identity> <Name>Example.SCOMMigration</Name> <References> <Reference Alias="SC"> <ID>Microsoft.SystemCenter.Library</ID> <Version>6.1.7221.0</Version> <PublicKeyToken>31bf3856ad364e35</PublicKeyToken> </Reference> <Reference Alias="Windows"> <ID>Microsoft.Windows.Library</ID> <Version>6.1.7221.0</Version> <PublicKeyToken>31bf3856ad364e35</PublicKeyToken> </Reference> <Reference Alias="Health"> <ID>System.Health.Library</ID> <Version>6.1.7221.0</Version> <PublicKeyToken>31bf3856ad364e35</PublicKeyToken> </Reference> <Reference Alias="System"> <ID>System.Library</ID> <Version>6.1.7221.0</Version> <PublicKeyToken>31bf3856ad364e35</PublicKeyToken> </Reference> </References> </Manifest> <TypeDefinitions> <EntityTypes> <ClassTypes> <ClassType ID="Example.SCOMMigration.OldMG" Accessibility="Internal" Abstract="false" Base="Windows!Microsoft.Windows.LocalApplication" Hosted="true" Singleton="false" /> </ClassTypes> </EntityTypes> <MonitorTypes> <UnitMonitorType ID="Example.SCOMMigration.OldMGExists.MonitorType" Accessibility="Internal"> <MonitorTypeStates> <MonitorTypeState ID="RegKeyExists" NoDetection="false" /> <MonitorTypeState ID="RegKeyMissing" NoDetection="false" /> </MonitorTypeStates> <Configuration /> <MonitorImplementation> <MemberModules> <DataSource ID="RegDS" TypeID="Windows!Microsoft.Windows.RegistryProvider"> <ComputerName>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$</ComputerName> <RegistryAttributeDefinitions> <RegistryAttributeDefinition> <AttributeName>OldMGExists</AttributeName> <Path>SYSTEM\CurrentControlSet\Services\HealthService\Parameters\Management Groups\OMMG</Path> <PathType>0</PathType> <AttributeType>0</AttributeType> </RegistryAttributeDefinition> </RegistryAttributeDefinitions> <Frequency>60</Frequency> </DataSource> <ConditionDetection ID="CDExists" TypeID="System!System.ExpressionFilter"> <Expression> <SimpleExpression> <ValueExpression> <XPathQuery Type="String">Values/OldMGExists</XPathQuery> </ValueExpression> <Operator>Equal</Operator> <ValueExpression> <Value Type="String">true</Value> </ValueExpression> </SimpleExpression> </Expression> </ConditionDetection> <ConditionDetection ID="CDMissing" TypeID="System!System.ExpressionFilter"> <Expression> <SimpleExpression> <ValueExpression> <XPathQuery Type="String">Values/OldMGExists</XPathQuery> </ValueExpression> <Operator>Equal</Operator> <ValueExpression> <Value Type="String">false</Value> </ValueExpression> </SimpleExpression> </Expression> </ConditionDetection> </MemberModules> <RegularDetections> <RegularDetection MonitorTypeStateID="RegKeyExists"> <Node ID="CDExists"> <Node ID="RegDS" /> </Node> </RegularDetection> <RegularDetection MonitorTypeStateID="RegKeyMissing"> <Node ID="CDMissing"> <Node ID="RegDS" /> </Node> </RegularDetection> </RegularDetections> </MonitorImplementation> </UnitMonitorType> </MonitorTypes> </TypeDefinitions> <Monitoring> <Discoveries> <Discovery ID="Example.SCOMMigration.OldMGDiscovery" Enabled="true" Target="Windows!Microsoft.Windows.Server.OperatingSystem" ConfirmDelivery="false" Remotable="true" Priority="Normal"> <Category>Discovery</Category> <DiscoveryTypes> <DiscoveryClass TypeID="Example.SCOMMigration.OldMG" /> </DiscoveryTypes> <DataSource ID="DS" TypeID="Windows!Microsoft.Windows.FilteredRegistryDiscoveryProvider"> <ComputerName>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$</ComputerName> <RegistryAttributeDefinitions> <RegistryAttributeDefinition> <AttributeName>AgentRegExists</AttributeName> <Path>SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Agent Management Groups</Path> <PathType>0</PathType> <AttributeType>0</AttributeType> </RegistryAttributeDefinition> </RegistryAttributeDefinitions> <Frequency>3600</Frequency> <ClassId>$MPElement[Name="Example.SCOMMigration.OldMG"]$</ClassId> <InstanceSettings> <Settings> <Setting> <Name>$MPElement[Name="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Name> <Value>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Value> </Setting> <Setting> <Name>$MPElement[Name="System!System.Entity"]/DisplayName$</Name> <Value>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$</Value> </Setting> </Settings> </InstanceSettings> <Expression> <SimpleExpression> <ValueExpression> <XPathQuery Type="String">Values/AgentRegExists</XPathQuery> </ValueExpression> <Operator>Equal</Operator> <ValueExpression> <Value Type="String">true</Value> </ValueExpression> </SimpleExpression> </Expression> </DataSource> </Discovery> </Discoveries> <Tasks> <Task ID="Example.SCOMMigration.RemoveOldMGTask" Accessibility="Internal" Enabled="true" Target="Example.SCOMMigration.OldMG" Timeout="300" Remotable="true"> <Category>Maintenance</Category> <WriteAction ID="Script" TypeID="Windows!Microsoft.Windows.ScriptWriteAction"> <ScriptName>RemoveOldMG.vbs</ScriptName> <Arguments /> <ScriptBody><![CDATA[On error resume next Dim objMSConfig Set objMSConfig = CreateObject("AgentConfigManager.MgmtSvcCfg") 'See if Mgmt Group exists Set objMG = objMSConfig.GetManagementGroup ("OMMG") If Err <> 0 Then wscript.echo "OMMG management group does not exist on this agent" wscript.quit End If 'Remove AD int or manually configured management group 'Check if AD Integration is enabled objADint = objMSConfig.GetActiveDirectoryIntegrationEnabled() If objADint <> 1 then wscript.echo "AD Integration is not enabled on this agent" wscript.echo "Removing old manually configured management group" Call objMSConfig.RemoveManagementGroup ("OMMG") else wscript.echo "AD Integration is enabled and returned value: " & objADint 'Disable AD Integration wscript.echo "Disabling AD Integration" Call objMSConfig.DisableActiveDirectoryIntegration() End If 'Restart agent healthservice out of band wscript.echo "Attempting to restart Healthservice out of band" dim strServiceName, objWMIService, colListofServices, objService strServiceName = "HealthService" dim sFilePath Dim objFSO 'As FileSystemObject Dim objTextFile 'As Object Dim oShell Set oShell = CreateObject( "WScript.Shell" ) temppath=oShell.ExpandEnvironmentStrings("%TMP%") 'wscript.echo "Temp Path" & temppath sText="net stop Healthservice && net start Healthservice" sFilePath=temppath & "\sshs.bat" 'wscript.echo "Writing to " & sFilePath Set objFSO = CreateObject("Scripting.FileSystemObject") Set objTextFile = objFSO.CreateTextFile(sFilePath, True) ' Write a line. objTextFile.Write (sText) objTextFile.Close oShell.run sFilePath]]></ScriptBody> <TimeoutSeconds>60</TimeoutSeconds> </WriteAction> </Task> </Tasks> <Monitors> <UnitMonitor ID="Example.SCOMMigration.OldMgExistsMonitor" Accessibility="Internal" Enabled="true" Target="Example.SCOMMigration.OldMG" ParentMonitorID="Health!System.Health.ConfigurationState" Remotable="true" Priority="Normal" TypeID="Example.SCOMMigration.OldMGExists.MonitorType" ConfirmDelivery="true"> <Category>Custom</Category> <OperationalStates> <OperationalState ID="UIGeneratedOpStateId12568c009a744c66a11a3d10f605a46a" MonitorTypeStateID="RegKeyExists" HealthState="Warning" /> <OperationalState ID="UIGeneratedOpStateIdfb9c9eca86164bdf99d155617a574b9e" MonitorTypeStateID="RegKeyMissing" HealthState="Success" /> </OperationalStates> <Configuration /> </UnitMonitor> </Monitors> </Monitoring> <Presentation> <Views> <View ID="Example.SCOMMigration.NewElement" Accessibility="Internal" Enabled="true" Target="Example.SCOMMigration.OldMG" TypeID="SC!Microsoft.SystemCenter.StateViewType" Visible="true"> <Category>Custom</Category> <Criteria /> </View> </Views> <Folders> <Folder ID="Example.SCOMMigration.FolderRoot" Accessibility="Internal" ParentFolder="SC!Microsoft.SystemCenter.Monitoring.ViewFolder.Root" /> </Folders> <FolderItems> <FolderItem ElementID="Example.SCOMMigration.NewElement" Folder="Example.SCOMMigration.FolderRoot" /> </FolderItems> </Presentation> <LanguagePacks> <LanguagePack ID="ENU" IsDefault="true"> <DisplayStrings> <DisplayString ElementID="Example.SCOMMigration"> <Name>Example SCOM Migration MP</Name> <Description /> </DisplayString> <DisplayString ElementID="Example.SCOMMigration.FolderRoot"> <Name>Example SCOM Migration</Name> <Description /> </DisplayString> <DisplayString ElementID="Example.SCOMMigration.NewElement"> <Name>Example SCOM Migration</Name> <Description /> </DisplayString> <DisplayString ElementID="Example.SCOMMigration.OldMG"> <Name>Old Management Group Class</Name> </DisplayString> <DisplayString ElementID="Example.SCOMMigration.OldMGDiscovery"> <Name>Old Management Group Class Discovery</Name> <Description /> </DisplayString> <DisplayString ElementID="Example.SCOMMigration.OldMGExists.MonitorType"> <Name>Old MG Exists MonitorType</Name> <Description /> </DisplayString> <DisplayString ElementID="Example.SCOMMigration.OldMgExistsMonitor"> <Name>Old Management Group Exists Monitor</Name> <Description /> </DisplayString> <DisplayString ElementID="Example.SCOMMigration.OldMgExistsMonitor" SubElementID="UIGeneratedOpStateId12568c009a744c66a11a3d10f605a46a"> <Name>RegKeyExists</Name> </DisplayString> <DisplayString ElementID="Example.SCOMMigration.OldMgExistsMonitor" SubElementID="UIGeneratedOpStateIdfb9c9eca86164bdf99d155617a574b9e"> <Name>RegKeyMissing</Name> </DisplayString> <DisplayString ElementID="Example.SCOMMigration.RemoveOldMGTask"> <Name>Remove Old ManagementGroup</Name> <Description /> </DisplayString> </DisplayStrings> </LanguagePack> </LanguagePacks> </ManagementPack>

My script is pretty simple – borrowing from a few examples above:

On error resume next Dim objMSConfig Set objMSConfig = CreateObject("AgentConfigManager.MgmtSvcCfg") 'See if Mgmt Group exists Set objMG = objMSConfig.GetManagementGroup ("OMMG") If Err <> 0 Then wscript.echo "OMMG management group does not exist on this agent" wscript.quit End If 'Remove AD int or manually configured management group 'Check if AD Integration is enabled objADint = objMSConfig.GetActiveDirectoryIntegrationEnabled() If objADint <> 1 then wscript.echo "AD Integration is not enabled on this agent" wscript.echo "Removing old manually configured management group" Call objMSConfig.RemoveManagementGroup ("OMMG") else wscript.echo "AD Integration is enabled and returned value: " & objADint 'Disable AD Integration wscript.echo "Disabling AD Integration" Call objMSConfig.DisableActiveDirectoryIntegration() End If 'Restart agent healthservice out of band wscript.echo "Attempting to restart Healthservice out of band" dim strServiceName, objWMIService, colListofServices, objService strServiceName = "HealthService" dim sFilePath Dim objFSO 'As FileSystemObject Dim objTextFile 'As Object Dim oShell Set oShell = CreateObject( "WScript.Shell" ) temppath=oShell.ExpandEnvironmentStrings("%TMP%") 'wscript.echo "Temp Path" & temppath sText="net stop Healthservice && net start Healthservice" sFilePath=temppath & "\sshs.bat" 'wscript.echo "Writing to " & sFilePath Set objFSO = CreateObject("Scripting.FileSystemObject") Set objTextFile = objFSO.CreateTextFile(sFilePath, True) ' Write a line. objTextFile.Write (sText) objTextFile.Close oShell.run sFilePath

Here is the view:

image

 

Health explorer for the monitor:

image

 

You can multi-select many agents and run the task:

 

image

 

Note – you MUST run the task as a user account that has local administrator rights on each agent.  If you run the task as the default agent action account (local system) the service will stop but not restart.  It is quite complicated to make a SCOM task that can reliably restart the SCOM service:

 

image

 

The output:

image

Comments
  • Thanks for the mention Kevin! There is also a new way! http://www.systemcentercentral.com/powershell-desired-state-configuration-dsc-resources-for-system-center-revisited/

  • I have scorch doing it for us, runs a task to add or remove a management group then runs the flush health service task which effectively reloads the configuration

  • Nice one, Thanks Kevin! Also, I managed to use DCM from ConfigMgr 2012 to enforce the correct management group is configured on OpsMgr 2012 agents: http://blog.tyang.org/2013/11/30/deploying-opsmgr-202-r2-agents-using-configmgr-part-2/

  • We didn't read the note about the Local Administaror Rights...and just wondered why the folks above are not stepped into this error.
    We found this workaround: Run schtasks.exe in a Wsshell.run to create a Scheduled Job executing the net stop , start commands. Some confirmation prompts of schtasks.exe was fulfilled with "schtasks.exe .... < yesfile.txt".="" of="" course="" yesfile.txt="" was="" created="" in="" same="" script="" using="" textfile.write("y"),="" textfile.writeln()="" will="" not="" work.="" this="" jobmanagement="" was="" quite="" tricky,="" but="" now="">
    Thanks again to Kevin. We will use the script in our migration project.

  • Hi Kevin, thanks for this...
    I have a question, it seems the mp does not seem to discover agenst on windows xp? Do I need to different discovery method?

  • Found out... replacing the Target of the discovery "Windows!Microsoft.Windows.Server.OperatingSystem" with "Windows!Microsoft.Windows.OperatingSystem" did the trick.

  • Having variable results with getting the Health Service to restart with a task. I'm running the Task with an account that is a member of an AD group which is, in turn, a member of the Administrators group on all our servers. Still however, I run into cases where after running task, the healthservice will stop but not start. Any idea why this might be?

    Thanks

  • @OdgeUK -

    Yes - this will almost never work. The problem is that whatever you do in script - it is being called by a monitoringhost.exe process. When we kill the healthservices for a restart, we kill these worker processes - and they in turn kill any cscript.exe processes - which make the restart unreliable. If you look at the health service restart that Microsoft supplies for the agent resources - we actually call into WMI - and create a new process "out of band" which makes it reliable. I'd recommend looking at that example and seeing if you can reuse.

  • Thanks Kevin! That sounds about right (althought it DOES work on a number of servers, but not on others, which I find a bit wierd). Will check into the Out of Band restart you have in your script. I wonder why we restart the Health Service? Doesn't Call objMSConfig.ReloadConfiguration make the changes effective anyway?

  • This monitor is working really well in identifying agents with old management groups. However, I have found that it's not picking up R2 servers. Any reason this might be?

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
Search Blogs