How to create a SCOM group from an Active Directory Computer Group




There have been a bunch of examples of this published over the years.  Some of them worked well, but I was never happy with many of them as they were often vbscript based, hard to troubleshoot, and required lots of editing each time you wanted to reuse them.  Many were often error prone, and didn’t work if the AD group contained computers that didn’t exist in SCOM, as SCOM will reject the entire discovery data payload in that case.

If you too were looking for a reliable and easy way to do this, well, look no further!  I have created an MP Fragment in my fragment library for this:


This MP Fragment will make creating SCOM groups of Windows Computers from Active Directory groups super easy!  This is a nice way to “delegate” the ability for end users to control what servers will appear in their scopes, as they often have the ability to easily add and remove computers from their AD groups, but they do not have access to SCOM Group memberships.

I am going to demonstrate using Silect MP Author Pro to reuse this Fragment, and you can also easily use Visual Studio with VSAE.  If you’d like to read more on either of those, see:


In Silect MP Author Pro – create a new, empty management pack, and select “Import Fragment”




Browse the fragment and choose:  Class.Group.ADGroupWindowsComputers.mpx



We need to simply input the values here, such as:



Click “Import

Silect MP Author Pro will automagically handle the references for you, so just say “Yes” on the popup:



That’s IT!   Surprised smile


Save it, and deploy it!



If you look in SCOM after a few minutes – you should see your group:




The rule to populate it runs once a day by default, but it will run immediately upon import.  Look for event ID 7500 in the OpsMgr event log on the Management Server that hosts your All Management Servers Resource Pool object



Once you see these events and no errors in them – you can view group membership in SCOM:




So easy.  And you don’t have to know anything about XML, or even Management Packs to do it!

Using Visual Studio with VSAE works exactly the same way – you simply have to do a manual Find/Replace for each item.  See the VSAE method in the link above.


Want to dig deeper into how this is put together?  Read on:

The MP we generate is very basic.  There is a Class (the Group definition) a Relationship (the Group contains Windows Computers) and a discovery (queries AD and discovers the relationship to the existing Windows Computers in SCOM)



The script is below:

We basically connect to AD, find the group by name, query to get members, look the membership up and see if they exist in SCOM, if they do, add them to the group.

We will log events along the way to help in troubleshooting if anything doesn’t work, and record the completion and total script runtime, like all my SCOM scripts.

#================================================================================= # Group Population script based on AD group membership # # Kevin Holman # v1.6 #================================================================================= param($SourceID, $ManagedEntityID, $ADGroup, $LDAPSearchPath) # Manual Testing section - put stuff here for manually testing script - typically parameters: #================================================================================= # $SourceId = '{00000000-0000-0000-0000-000000000000}' # $ManagedEntityId = '{00000000-0000-0000-0000-000000000000}' # $ADGroup = "SCOM Computers Group" # $LDAPSearchPath = "LDAP://DC=opsmgr,DC=net" #================================================================================= # Constants section - modify stuff here: #================================================================================= # Assign script name variable for use in event logging $ScriptName = "##CompanyID##.##AppName##.##GroupNameNoSpaces##.ADBased.Group.Discovery.ps1" $EventID = "7500" #================================================================================= # Starting Script section - All scripts get this #================================================================================= # Gather the start time of the script $StartTime = Get-Date # Load MOMScript API $momapi = New-Object -comObject MOM.ScriptAPI # Load SCOM Discovery module $DiscoveryData = $momapi.CreateDiscoveryData(0, $SourceId, $ManagedEntityId) #Set variables to be used in logging events $whoami = whoami #Log script event that we are starting task $momapi.LogScriptEvent($ScriptName,$EventID,0,"`n Script is starting. `n Running as ($whoami).") #================================================================================= # Connect to local SCOM Management Group Section #================================================================================= # Clear any previous errors $Error.Clear() # Import the OperationsManager module and connect to the management group $SCOMPowerShellKey = "HKLM:\SOFTWARE\Microsoft\System Center Operations Manager\12\Setup\Powershell\V2" $SCOMModulePath = Join-Path (Get-ItemProperty $SCOMPowerShellKey).InstallDirectory "OperationsManager" Import-module $SCOMModulePath New-DefaultManagementGroupConnection "localhost" IF ($Error) { $momapi.LogScriptEvent($ScriptName,$EventID,1,"`n FATAL ERROR: Failure loading OperationsManager module or unable to connect to the management server. `n Terminating script. `n Error is: ($Error).") EXIT } #================================================================================= # Begin MAIN script section #================================================================================= #Log event for captured parameters $momapi.LogScriptEvent($ScriptName,$EventID,0,"`n ADGroup: ($ADGroup) `n LDAP search path: ($LDAPSearchPath).") # Health Service class section # We need this list of SCOM agents, so we can only submit discovery data for a Healthservice in SCOM otherwise SCOM will reject the discovery data, and this will clean up deleted stale Windows Computer objects that will remain until the next discovery # Clear any previous errors $Error.Clear() # Get all instances of a existing Health Service class $HS = Get-SCOMClass -Name "Microsoft.SystemCenter.Healthservice" | Get-SCOMClassInstance $HSNames = $HS.DisplayName $HSCount = $HSNames.count IF($Error) { $momapi.LogScriptEvent($ScriptName,$EventID,1, "`n FATAL ERROR: Unable to gather Healthservice instances from SCOM. `n Error is: $Error") EXIT } ELSE { $momapi.LogScriptEvent($ScriptName,$EventID,0, "`n Get all Health Service Objects from SCOM has completed. `n Returned ($HSCount) Health Service Objects from SCOM.") } # END Health Service class section # Connect to AD using LDAP search to find the DN for the Group $Searcher = New-Object DirectoryServices.DirectorySearcher $Searcher.Filter = '(&(objectCategory=group)(cn=' + $ADGroup + '))' $Searcher.SearchRoot = $LDAPSearchPath $Group = $Searcher.FindAll() IF ($Error) { $momapi.LogScriptEvent($ScriptName,$EventID,1,"`n FATAL ERROR: Failure getting data from AD for ($ADGroup). `n Terminating script. `n Error is: ($Error).") EXIT } $GroupDN = @() # Now that we have the group object, trim to get the DN in order to search for members $GroupDN = $Group.path.TrimStart("LDAP://") #If we found the group in AD by the DisplayName log a success event otherwise log error IF ($GroupDN) { $momapi.LogScriptEvent($ScriptName,$EventID,0,"`n Successfully found group in AD. `n ADGroup: ($ADGroup) `n GroupDN: ($GroupDN).") } ELSE { $momapi.LogScriptEvent($ScriptName,$EventID,1,"`n FATAL ERROR: Did not find group in AD: ($ADGroup) using ($LDAPSearchPath). `n Terminating script.") EXIT } # Search for members of the group $Searcher = New-Object DirectoryServices.DirectorySearcher $Searcher.Filter = '(&(objectCategory=computer)(memberOf=' + $GroupDN + '))' $ADComputerObjects = $Searcher.FindAll() $ADComputerObjectsCount = $ADComputerObjects.Count If ($ADComputerObjectsCount -gt 0) { $momapi.LogScriptEvent($ScriptName,$EventID,0,"`n Successfully found ($ADComputerObjectsCount) members in the group. `n ADGroup: ($ADGroup) `n GroupDN: ($GroupDN).") } Else { $momapi.LogScriptEvent($ScriptName,$EventID,1, "`n FATAL ERROR: Did not find any members in the AD group. `n ADGroup: ($ADGroup) `n GroupDN: ($GroupDN). `n Terminating script.") EXIT } # Set namelist array to empty $NameList = @() # Loop through each computer object and build an array of FQDN hostnames FOREACH ($ADComputerObject in $ADComputerObjects) { #Get the DNS Hostname property from AD [string]$DNSComputerName = $ADComputerObject.Properties.dnshostname #Only add the name to the array if the DNSHostname property exists in AD IF ($DNSComputerName) { $NameList += $DNSComputerName } } $NameListCount = $NameList.Count IF ($NameListCount -ge 1) { $momapi.LogScriptEvent($ScriptName,$EventID,0,"`n Successfully found ($NameListCount) DNS Names from the original ($ADComputerObjectsCount) members in the group. `n ADGroup: ($ADGroup) `n GroupDN: ($GroupDN).") } ELSE { $momapi.LogScriptEvent($ScriptName,$EventID,1,"`n FATAL ERROR: There was an error getting DNS Host Names or none were found for members of the group. `n Group objects count: ($ADComputerObjectsCount). `n ADGroup: ($ADGroup) `n GroupDN: ($GroupDN). `n Terminating script.") EXIT } #Discovery Section #Set the group instance we will discover members of $GroupInstance = $DiscoveryData.CreateClassInstance("$MPElement[Name='##CompanyID##.##AppName##.##GroupNameNoSpaces##.ADBased.Group']$") # Loop through each SCOM computer and add a group membership containment relationship to the discovery data $i=0; FOREACH ($Name in $NameList) { #Check to make sure the name we got from AD exists as a Healthservice in this Management Group IF ($Name -in $HSNames) { $i = $i+1 $ServerInstance = $DiscoveryData.CreateClassInstance("$MPElement[Name='Windows!Microsoft.Windows.Computer']$") $ServerInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $Name) $RelationshipInstance = $DiscoveryData.CreateRelationshipInstance("$MPElement[Name='##CompanyID##.##AppName##.##GroupNameNoSpaces##.ADBased.Group.Contains.Windows.Computers']$") $RelationshipInstance.Source = $GroupInstance $RelationshipInstance.Target = $ServerInstance $DiscoveryData.AddInstance($RelationshipInstance) } } IF ($i -ge 1) { $momapi.LogScriptEvent($ScriptName,$EventID,0,"`n Successfully found ($i) Computers in SCOM from the original ($NameListCount) DNS names pulled from the group. `n ADGroup: ($ADGroup) `n GroupDN: ($GroupDN).") } ELSE { $momapi.LogScriptEvent($ScriptName,$EventID,1,"`n FATAL ERROR: No computers in SCOM were found matching the ($NameListCount) DNS names pulled from the group. `n Group objects: ($ADComputerObjectsCount). `n ADGroup: ($ADGroup) `n GroupDN: ($GroupDN). `n Terminating script.") EXIT } # Return Discovery Items Normally $DiscoveryData # Return Discovery Bag to the command line for testing (does not work from ISE) # $momapi.Return($DiscoveryData) #================================================================================= # End MAIN script section # End of script section #================================================================================= #Log an event for script ending and total execution time. $EndTime = Get-Date $ScriptTime = ($EndTime - $StartTime).TotalSeconds $momapi.LogScriptEvent($ScriptName,$EventID,0,"`n Script Ending. `n Script Runtime: ($ScriptTime) seconds.") #=================================================================================


Key recommendations:

1.  Don’t run your frequency <intervalseconds> too often.  If updating the group once a day is ok, leave it at the default.  If you need it more frequent, that’s fine, just remember it’s a script, and all scripts running on the management servers have an impact on the overall load, plus we are submitting discovery data about relationships each time, and searching through AD.

2.  The default timeout is set to 5 minutes.  If you cannot complete this in less, something is WRONG and it most likely will be how long it takes to find the group in AD.  If that is true for you, you need to optimize the section on querying AD and LDAP search path.

3.  If you have a lot of AD based SCOM groups, consider adding a staggered sync time to each discovery, so they don’t all run at the same time, or on the same interval.

Comments (12)

  1. Great work on this Kevin. It should have ben default, just as OU if you ask me.
    Looking at the script now, will it work with nested groups? I want to create scom groups based on some maintenance groups defined in AD, but these are nested, and will need to search for computers recursively. Dosent look to me as this will work with the current script

    Martin Ehrnst

    1. Kevin Holman says:

      OU is easy – because a computer only has a single OU…. so it makes sense to have an OU as a class property – it has a 1:1 relationship with an object (a computer can only exist in one OU) and it doesn’t change often. That makes it an excellent candidate for a class property – which is it, which made grouping easy.

      AD group membership is not 1:1 – a computer can be a member of thousands of AD groups – so discovering this out of the box doesn’t make sense based on SCOM’s design. What they COULD have done is create a group authoring template, that is based on a module that queries AD and populates the group, but that would be VERY different than the core design – which is grouping based on class properties. What makes this easy to use now is a well written script that works, and MP fragments to make them easily reusable.

      Now – on your question about SCOM and AD nested groups – I don’t understand the ask. Are the groups nested in AD or SCOM? Can you describe this a little better? I bet we can figure something out.

      1. Hi Kevin, id did not mean a class property, but the ability to create group based on AD computer groups (as you did here)
        On to my question.I took a brief look at your script as i need to create SCOM groups based on AD groups that represent our patch windows (don’t ask why).
        Our AD groups are nested and only contains other computer groups. As far as I can see, you script does not work in this case, I can try to see if i’m able to create something with your script as base source ( i dont want to rely on the AD PS modules and such)


  2. Anonymous says:
    (The content was deleted per user request)
  3. bsuresh says:

    This is an excellent blog, Kevin! I have used Visual Studio and created an MP and it is working fine! As we are with SCOM 2016, we can schedule Maintenance Mode for AD groups as our patching is based on AD group names.
    Question – We have around 20 plus AD groups specific for environments like Dev, Stage and Prd and for various time window. Can we use same MP to discover multiple AD groups and to create SCOM group names based on it? If yes, can you point me the direction to achieve it.

    1. bsuresh says:

      This is to update that I have edited an MP to discover multiple AD groups. All you need to do is to rewrite five HTML tags with the appropriate name in it. But, one challenge is that script code will be also pasted multiple times while adding the AD group. So, our XML will be lengthy in lines. If anyone have other option, that will be great.

      1. Kevin Holman says:

        This is one of the downsides to using fragments – you do not get the benefit of shared data sources as easily. To reduce your AD based Group MP’s XML size and duplication of the script – you’d need to use a shared datasource sealed in a library MP, then have each discovery reference this shared script datasource, and pass the important variables that change, like AD group name, etc.

        1. bsuresh says:

          Thanks for your reply, Kevin! I will try to create a Library MP and implement as you mentioned. As I am not good with Authoring, will read more blogs and create. Thanks again!

  4. Mithun Raj says:

    Hello Kevin, thank you for this great post. Just wondering if you know of any issues with the foreign domain? I can get the SCOM group from AD group as long as the domain is same as that of SCOM management server. If the domain is different, SCOM groups are not populating. We have multiple domains and some of them are in the DMZ. Event 7500 says FATAL ERROR: Did not find any members in the AD group. I use gateways to monitor servers in different domains. Any insight will be helpful. Thank you!

    1. edsun says:

      Kevin, I got the same error. Please help.

      ABC.ADgroupTest1.MyTestGroup.ADBased.Group.Discovery.ps1 :
      FATAL ERROR: No computers in SCOM were found matching the (10) DNS names pulled from the group.
      Group objects: (10).
      ADGroup: (Test-Green-Computers)
      GroupDN: (CN=Test-Green-Computers,OU=Group1 – Global,OU=Test Objects,OU=ABC Company,DC=ABC,DC=Dept1,DC=local).
      Terminating script.

      Thanks. Ed.

      1. Anonymous says:
        (The content was deleted per user request)
      2. edsun says:

        I found out the cause of the error by looking at the PS code in the fragment. None of the machines in the AD group is managed by the SCOM management server (under the health check). And that caused the error. I picked a different group, and the fragment worked without error. Ed

Skip to main content