locked
Issue with Script Based Discovery RRS feed

  • Question

  • Has anyone been successful with creating script based discovery using MPAuthor?

    I have created a very basic discovery script in PowerShell following the logic provided by Brian Wren in his Channel9 training videos. It looks for a few folders in a directory and adds the name and path as property values.

    The script executes without error natively in Powershell and returns the desired properties within the XML generated. The agent will also execute the workflow without error after the management pack has been imported.

    My issue is that nothing is discovered and the management server generates an error when it receives the discovery data from the agent in the operations manager event log:

    Microsoft.EnterpriseManagement.Common.DiscoveryDataInvalidClassPropertyValueException,The class property value specified in the discovery data item is not valid. The value needs to adhere to the class. Class property name: MPElement[Name=’MPAuthor.Classname’]/FolderPath$ Class property value: C:\foldername\childfolder

    If I’m being honest I don’t really understand what this error means and google so far hasn’t returned anything helpful. Any help would be appreciated.

    I have checked that the property values are the correct type, in this case I have specified string values.

    Thanks


    • Edited by JohnnyKT28 Tuesday, June 28, 2016 10:46 AM
    Monday, June 27, 2016 1:58 PM

All replies

  • can you post your mp/xml?

    Rob Korving
    http://jama00.wordpress.com/

    Monday, June 27, 2016 2:12 PM
  • 

    Sure thing.

    I've basically tried to mimic the script discovery part of the Channel9 training using MP author.

    <?xml version="1.0" encoding="utf-8"?><ManagementPack ContentReadable="true" SchemaVersion="2.0" OriginalSchemaVersion="1.1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <Manifest>
        <Identity>
          <ID>MPAuthorDiscoScript</ID>
          <Version>1.0.0.3</Version>
        </Identity>
        <Name>MPAuthorDiscoScript</Name>
        <References>
          <Reference Alias="SCInternal">
            <ID>Microsoft.SystemCenter.Internal</ID>
            <Version>7.0.8432.0</Version>
            <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
          </Reference>
          <Reference Alias="Windows">
            <ID>Microsoft.Windows.Library</ID>
            <Version>7.5.8501.0</Version>
            <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
          </Reference>
          <Reference Alias="Performance">
            <ID>System.Performance.Library</ID>
            <Version>7.0.8432.0</Version>
            <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
          </Reference>
          <Reference Alias="System">
            <ID>System.Library</ID>
            <Version>7.5.8501.0</Version>
            <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
          </Reference>
          <Reference Alias="SC">
            <ID>Microsoft.SystemCenter.Library</ID>
            <Version>7.0.8432.0</Version>
            <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
          </Reference>
          <Reference Alias="Health">
            <ID>System.Health.Library</ID>
            <Version>7.0.8432.0</Version>
            <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
          </Reference>
        </References>
      </Manifest>
      <TypeDefinitions>
        <EntityTypes>
          <ClassTypes>
            <ClassType ID="MPAuthor.Stores.Queue" Accessibility="Public" Abstract="false" Base="Windows!Microsoft.Windows.ApplicationComponent" Hosted="false" Singleton="false" Extension="false">
              <Property ID="FolderPath" Type="string" AutoIncrement="false" Key="false" CaseSensitive="false" MaxLength="256" MinLength="0" Required="false" Scale="0" />
              <Property ID="StoreCode" Type="string" AutoIncrement="false" Key="true" CaseSensitive="false" MaxLength="256" MinLength="0" Required="false" Scale="0" />
            </ClassType>
          </ClassTypes>
        </EntityTypes>
      </TypeDefinitions>
      <Monitoring>
        <Discoveries>
          <Discovery ID="MPAuthor.Stores.Queue.Discovery" Enabled="false" Target="Windows!Microsoft.Windows.Server.Computer" ConfirmDelivery="false" Remotable="true" Priority="Normal">
            <Category>Discovery</Category>
            <DiscoveryTypes>
              <DiscoveryClass TypeID="MPAuthor.Stores.Queue">
                <Property TypeID="MPAuthor.Stores.Queue" PropertyID="StoreCode" />
                <Property TypeID="MPAuthor.Stores.Queue" PropertyID="FolderPath" />
                <Property TypeID="System!System.ConfigItem" PropertyID="ObjectStatus" />
                <Property TypeID="System!System.ConfigItem" PropertyID="AssetStatus" />
                <Property TypeID="System!System.ConfigItem" PropertyID="Notes" />
                <Property TypeID="System!System.Entity" PropertyID="DisplayName" />
              </DiscoveryClass>
            </DiscoveryTypes>
            <DataSource ID="DS" TypeID="Windows!Microsoft.Windows.TimedPowerShell.DiscoveryProvider">
              <IntervalSeconds>60</IntervalSeconds>
              <SyncTime />
              <ScriptName>DiscoveryScript2.ps1</ScriptName>
              <ScriptBody>
    param($sourceId,$managedEntityId,$topFolder,$computerName)
    
    $api = New-Object -ComObject 'MOM.ScriptAPI'
    $discoveryData = $api.CreateDiscoveryData(0, $sourceId, $managedEntityId)
    
    $subFolders = Get-ChildItem -Path $topFolder | where {$_.psIsContainer -eq $true}
    foreach ($subfolder in $subFolders)
    {
        $instance = $discoveryData.CreateClassInstance("$MPElement[Name='MPAuthor.Stores.Queue']$")
    
        $instance.AddProperty("MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipleName$", $computerName)
        $instance.AddProperty("MPElement[Name='MPAuthor.Stores.Queue']/StoreCode$", $subfolder.Name)
        $instance.AddProperty("MPElement[Name='MPAuthor.Stores.Queue']/FolderPath$", $subfolder.FullName)
    
        $discoveryData.AddInstance($instance)
    }
    
    $discoveryData
    </ScriptBody>
              <Parameters>
                <Parameter>
                  <Name>sourceId</Name>
                  <Value>$MPElement$</Value>
                </Parameter>
                <Parameter>
                  <Name>managedEntityId</Name>
                  <Value>$Target/Id$</Value>
    			</Parameter>  
    			<Parameter>
    			  <Name>topFolder</Name>
    			  <Value>D:\Discotest</Value>
                </Parameter>
                <Parameter>
                  <Name>computerName</Name>
                  <Value>$Target/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Value>
                </Parameter>
              </Parameters>
              <TimeoutSeconds>300</TimeoutSeconds>
              <StrictErrorHandling>false</StrictErrorHandling>
            </DataSource>
          </Discovery>
        </Discoveries>
        <Overrides>
          <DiscoveryPropertyOverride ID="OverrideForDiscoveryMPAuthorStoresQueueDiscoveryForContextMicrosoftWindowsComputer1e7e3dcd0c0a49278cacebfc300ba4ce" Context="Windows!Microsoft.Windows.Computer" ContextInstance="565ff7bf-f7bc-02f0-7e90-07ae22874a29" Enforced="false" Discovery="MPAuthor.Stores.Queue.Discovery" Property="Enabled">
            <Value>true</Value>
          </DiscoveryPropertyOverride>
        </Overrides>
      </Monitoring>
      <LanguagePacks>
        <LanguagePack ID="ENU" IsDefault="true">
          <DisplayStrings>
            <DisplayString ElementID="MPAuthor.Stores.Queue">
              <Name>MPAuthor Stores Queue</Name>
            </DisplayString>
            <DisplayString ElementID="MPAuthor.Stores.Queue.Discovery">
              <Name>MPAuthor Stores Queue Discovery</Name>
              <Description>Created using MP Author</Description>
            </DisplayString>
            <DisplayString ElementID="MPAuthor.Stores.Queue" SubElementID="FolderPath">
              <Name>FolderPath</Name>
            </DisplayString>
            <DisplayString ElementID="MPAuthor.Stores.Queue" SubElementID="StoreCode">
              <Name>StoreCode</Name>
            </DisplayString>
            <DisplayString ElementID="MPAuthorDiscoScript">
              <Name>MPAuthorDiscoScript</Name>
            </DisplayString>
          </DisplayStrings>
        </LanguagePack>
      </LanguagePacks>
    </ManagementPack>


    Tuesday, June 28, 2016 7:25 AM
  • I've stared at the code for awhile and I'm not seeing anything super obvious jump out at me. So I'll just throw this thought out there. Maybe something like referencing the subfolder property when you're adding the instance property and/or something like a space in the folder path is causing issues?

    Try this:

        $Name = $Subfolder.name
        $FullName = $Subfolder.fullname

        $instance.AddProperty("MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipleName$", $computerName)
        $instance.AddProperty("MPElement[Name='MPAuthor.Stores.Queue']/StoreCode$", $Name)
        $instance.AddProperty("MPElement[Name='MPAuthor.Stores.Queue']/FolderPath$", $FullName)

    You could also try putting "$FullName" when you're adding the property as well but I don't think that should matter. If the above doesn't fix it you could try testing further by controlling the data you're inserting into FolderPath by just explicitly calling it something like "c:\blahblabhblah" and see if you get the same error. If that works then you definitely know its not liking something you're getting from get-childitem. If you have visual studio you can try MP Simulator to test as well. I think MP Simulator (a little bit about it here: http://social.technet.microsoft.com/wiki/contents/articles/19137.visual-studio-authoring-extensions-management-pack-tools.aspx) is only available in visual studio authoring extensions anyway? I just learned about it the other day, I haven't used it yet, but it looks pretty cool.

    oh yeah, one last thought. What version of PowerShell is running on the server? If its 2.0 (or less maybe?) I think if you do a ForEach on a null object (ie: no folders where returned from you get-childitem) it will still iterate through the loop once which would be likely to make SCOM angry.

    Tuesday, June 28, 2016 7:28 PM
  • I think you miss a few basics here. not sure where the error is coming from as it seems cryptic to me too, but pretty sure what you wrote isn't going to work.

    $instance.AddProperty("MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipleName$",$computerName)

    With this you are trying to define a the principle name of the windows computer class, but you defined your class as unhosted which means it doesn't have a relationship to a computer. That's probably not correct. I'm pretty sure if you look at the mpauthor example it has a "localapplication" or "computerrole" class defined and this application component class has a hosting relationship with that class or it is in fact uses localapplication class as a base class.

    Maybe some more reading about authoring first:

    http://social.technet.microsoft.com/wiki/contents/articles/15251.system-center-management-pack-authoring-guide.aspx


    Rob Korving
    http://jama00.wordpress.com/

    Wednesday, June 29, 2016 8:12 AM
  • Good catch Rob, I missed that he was using a base class of "Windows!Microsoft.Windows.ApplicationComponent". I wrongfully assumed it was Windows Computer or something like that. However I think your statements are only partly correct. It's true that Johnny would not need to add the property instance of PrincipalName for windows computer in the discovery but its isn't because it's not hosted. The reason is because ApplicationComponent doesn't inherit any PrincipalName property from Windows Computer. Its not in its class hierarchy. This is the class hierarchy for ApplicationComponent:

    System.Entity
    ExpandSystem.ConfigItem
    ExpandSystem.LogicalEntity
    ExpandSystem.ApplicationComponent
    Microsoft.Windows.ApplicationComponent

    PrincipalName should not be needed in this circumstance. I believe if he had a base class of Windows Computer (or another class based off it) he would still need to populate the key property of PrincipalName for Windows Computer. Whether or not a class is hosted the class hierarchy requires all key properties be populated within its hierarchy regardless of hosted being true/false. I think that's correct anyway, I had a hard time finding documentation that plainly points that out, but I believe its true.

    The bottom line is that I think we both agree that Johnny shouldn't need this line in the code:

    $instance.AddProperty("MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipleName$", $computerName)

    Due to the error he got I'm still suspect of both how he's populating the folderpath property and/or the data that is being returned. 

    • Proposed as answer by Elton_Ji Friday, July 8, 2016 10:20 AM
    Wednesday, June 29, 2016 5:41 PM
  • Hi, sorry this is an old post, I know, but if I see this right, you missed a $ sign infront of all MPElement in your Script.

    $instance.AddProperty("MPElement[Name=

    it should be:

    $instance.AddProperty("$MPElement[Name=

    So the one part would look like:

    $instance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipleName$", $computerName)
    $instance.AddProperty("$MPElement[Name='MPAuthor.Stores.Queue']/StoreCode$", $subfolder.Name)
    $instance.AddProperty("$MPElement[Name='MPAuthor.Stores.Queue']/FolderPath$", $subfolder.FullName)

    Monday, December 18, 2017 8:01 PM