J’avais publié il y a quelques années un article montrant comment créer et peupler automatiquement des groupes à partir d’une clé de registre, à l’aide d’un script vbs : Création et peuplement dynamique de groupes à partir d’une clé de registre.
J’ai récemment rencontré un besoin similaire, et j’ai cette fois voulu expérimenter une technique différente et que je considère comme plus élégante, car elle ne se base que sur l’utilisation standard de deux modules natifs, sans faire appel au moindre bout de script.
Je ne reviendrai pas ici sur la nécessité de déclarer une classe unhosted, non singleton et avec un attribut clé pour le groupe : tout cela est détaillé dans l’article précédent.
Entrons donc directement dans le vif du sujet !
Comme je viens de le rappeler, un groupe est l’instance d’une classe. Les objets membres de ce groupe sont eux aussi des instances de différentes classe et ils sont rattachés au groupe à l’aide d’une relation de containment.
Notre objectif est donc de créer des instances de la classe du groupe ainsi que des relations de containment entre ces instances et les objets qui vont venir peupler les groupes.
Et pour ce faire, sans utiliser aucun script, il existe un module parfaitement adapté : System.Discovery.FilteredClassAndRelationshipSnapshotDataMapper.
Ce module va tout simplement créer une instance de la classe que vous lui indiquerez, avec les propriétés que vous lui indiquerez ; ainsi qu’une instance de la relation de votre choix, entre les instances indiquées.
Bien entendu, il n’est pas question ici de remplir les champs de manière statique : ce module sera intégré dans votre workflow de découverte et récupérera donc toutes les informations dont il a besoin depuis les modules précédents.
Dans cet exemple, nous souhaitons peupler les groupes à partir d’une clé de registre : nous devrions donc créer notre datasourcemoduletype avec le très classique module Microsoft.Windows.Discovery.RegistryProvider comme datasource, puisque son rôle est justement d’aller lire dans la base de registre.
Mais il existe une solution encore plus simple : un module natif combinant RegistryProvider et SnapshotDataMapper existe déjà ! Il s’agit du module Microsoft.Windows.FilteredRegistryClassAndRelationshipDiscoveryProvider.
Une fois ces éléments mis bout à bout, on arrive au fragment suivant qu’il suffit de modifier en y indiquant la clé de registre qui vous intéresse :
<ManagementPackFragment SchemaVersion="2.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<TypeDefinitions>
<EntityTypes>
<ClassTypes>
<ClassType ID="Test.My.Computers.Group" Accessibility="Public" Abstract="false" Base="MSIL!Microsoft.SystemCenter.InstanceGroup" Hosted="false" Singleton="false" Extension="false" >
<Property ID="RegistryValue" Type="string" AutoIncrement="false" Key="true" CaseSensitive="false" MaxLength="256" MinLength="0" Required="false" Scale="0" />
</ClassType>
</ClassTypes>
</EntityTypes>
</TypeDefinitions>
<Monitoring>
<Discoveries>
<Discovery ID="Test.My.Computers.Group.Discovery" Enabled="true" Target="Windows!Microsoft.Windows.OperatingSystem" ConfirmDelivery="false" Remotable="true" Priority="Normal">
<Category>Discovery</Category>
<DiscoveryTypes>
<DiscoveryClass TypeID="Test.My.Computers.Group">
<Property TypeID="Test.My.Computers.Group" PropertyID="RegistryValue" />
</DiscoveryClass>
</DiscoveryTypes>
<DataSource ID="DS" TypeID="Windows!Microsoft.Windows.FilteredRegistryClassAndRelationshipDiscoveryProvider">
<ComputerName>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</ComputerName>
<RegistryAttributeDefinitions>
<RegistryAttributeDefinition>
<AttributeName>RegistryValueExists</AttributeName>
<Path>SOFTWARE\Test\RegistryValue</Path>
<PathType>1</PathType>
<!-- 0=regKey 1=regValue -->
<AttributeType>0</AttributeType>
<!-- 0=CheckIfExists (Boolean) 1=treat data as (String) 2=treat data as (Integer) -->
</RegistryAttributeDefinition>
<RegistryAttributeDefinition>
<AttributeName>RegistryValue</AttributeName>
<Path>SOFTWARE\Test\RegistryValue</Path>
<PathType>1</PathType>
<!-- 0=regKey 1=regValue -->
<AttributeType>1</AttributeType>
<!-- 0=CheckIfExists (Boolean) 1=treat data as (String) 2=treat data as (Integer) -->
</RegistryAttributeDefinition>
</RegistryAttributeDefinitions>
<Frequency>14400</Frequency>
<ClassId>$MPElement[Name="Test.My.Computers.Group"]$</ClassId>
<ClassInstanceSettings>
<Settings>
<Setting>
<Name>$MPElement[Name='System!System.Entity']/DisplayName$</Name>
<Value>Test My Group - $Data/Values/RegistryValue$</Value>
</Setting>
<Setting>
<Name>$MPElement[Name='Test.My.Computers.Group']/RegistryValue$</Name>
<Value>$Data/Values/RegistryValue$</Value>
</Setting>
</Settings>
</ClassInstanceSettings>
<RelationshipId>$MPElement[Name="MSIL!Microsoft.SystemCenter.InstanceGroupContainsEntities"]$</RelationshipId>
<SourceTypeId>$MPElement[Name="Test.My.Computers.Group"]$</SourceTypeId>
<SourceRoleSettings>
<Settings>
<Setting>
<Name>$MPElement[Name='Test.My.Computers.Group']/RegistryValue$</Name>
<Value>$Data/Values/RegistryValue$</Value>
</Setting>
</Settings>
</SourceRoleSettings>
<TargetTypeId>$MPElement[Name="Windows!Microsoft.Windows.Computer"]$</TargetTypeId>
<TargetRoleSettings>
<Settings>
<Setting>
<Name>$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$</Name>
<Value>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Value>
</Setting>
</Settings>
</TargetRoleSettings>
<Expression>
<SimpleExpression>
<ValueExpression>
<XPathQuery Type="Boolean">Values/RegistryValueExists</XPathQuery>
</ValueExpression>
<Operator>Equal</Operator>
<ValueExpression>
<Value Type="Boolean">true</Value>
</ValueExpression>
</SimpleExpression>
</Expression>
</DataSource>
</Discovery>
</Discoveries>
</Monitoring>
<LanguagePacks>
<LanguagePack ID="ENU" IsDefault="true">
<DisplayStrings>
<DisplayString ElementID="Test.My.Computers.Group">
<Name>Test Computers Group</Name>
</DisplayString>
<DisplayString ElementID="Test.My.Computers.Group.Discovery">
<Name>Test Computers Group Discovery</Name>
<Description>This discovery rule creates and populates groups of Windows Computer Objects that contain a registry key, based on this key's value</Description>
</DisplayString>
</DisplayStrings>
</LanguagePack>
</LanguagePacks>
</ManagementPackFragment>