How to collect custom inventory using PowerShell scripts via standalone package
search cancel

How to collect custom inventory using PowerShell scripts via standalone package

book

Article ID: 376499

calendar_today

Updated On:

Products

Inventory Solution

Issue/Introduction

Inventory Solution 8.7.3 introduces support of PowerShell script to be used in custom scripts via standaloone package.

Document provides examples.

Environment

8.7.3 and above

Resolution

  1. Create custom dataclass to store required data.

    This may be done using Manage Custom Data Classes page (Settings> Discovery and Inventory> Inventory Solution> Manage Custom Data Classes):

    1. Click New data class and define data class name

    2. Define data class scheme (add data class attributes aka columns)
    3. Save changes.
    4. Select created data class from the list and note its name and guid

     

  2. Create XML file containing data class definition, PowerShell script and mapping script output with data class columns. Separate XML file should be created for each custom data class. Format of file is the following: 
    <dataClass name="PowerShell_Test" GUID="{75b93ad9-1f2a-448a-a8f3-bf27ee0153d4}">
     <approaches>
      <approach type="script">
       <commands>
        <command scriptType="powershell" function="" timeout="2400000">
         <scriptText>
         		<![CDATA[
    			
    #some function to return true if integer is even
    function IsEven([int]$number) {
        if ($number % 2 -eq 0) {
            return $true
        } else {
            return $false
        }
    }
    
    $resultset = @{} 
    
    #sample for getting SymInv_GetRegistryValue
    $Key = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion"
    $ValueName = "ProductName"
    $regData = SymInv_GetRegistryValue -RegistryPath $Key -ValueName $ValueName
    
    #sample for getting SymInv_RunWmiQuery
    $wmiQuery = "SELECT * FROM Win32_Printer"
    $wmiData = SymInv_RunWmiQuery $wmiQuery
    
    $strUsername = $env:USERNAME
    $i = 100
    $currentDate = Get-Date
    $dateCurrent = $currentDate.ToString("yyyy-MM-dd")
    
    
    foreach ($wmiItem in $wmiData) {
        $rowDictionary = @{}  
        $isEvenCount = IsEven $i
        $rowDictionary["c0"] = $i
        $rowDictionary["c1"] = $strUsername
        $rowDictionary["c2"] = $isEvenCount
        $rowDictionary["c3"] = $dateCurrent
        $rowDictionary["c4"] = $wmiItem.Caption
        $rowDictionary["c5"] = $regData
        $resultset.Add($resultset.Count, $rowDictionary)
        $i=$i+1
        
    }
    
    $outResult = SymInv_GetDataclassResults $resultset
    
    $outResult #output result
    
    ]]>
        </scriptText>
         <properties>
         		<property mapsTo="0">incrementingInt</property>
          		<property mapsTo="1">usernameFromEnv</property>
    			<property mapsTo="2">bool_IsEvenInt</property>
    			<property mapsTo="3">date_fromPSCommand</property>
    			<property mapsTo="4">PrinterNameFromWmiOutput</property>
    			<property mapsTo="5">regOutput</property>
         </properties>
        </command>
       </commands>
      </approach>
     </approaches>
    </dataClass>
    

    Highlighted part is subject to be changed. Remaining parts are mandatory and should not be modified:

    • Define data class name and GUID. Values should match values from step 1d.
    • Define script timeout value in miliseconds
    • Modify script body so that it returns string like <row c0=”field01” c1=”filed02”\> <row c0=”field11” c1=”filed12”\> <row c0=”field21” c1=”filed22”\>’. We recommend to use predefined function SymInv_GetDataclassResults() – it returns correct string generating it from dictionary of output values(see provided sample and Appendix A)
    • Define mapping. It is required to define <property mapsTo="0">value1</property> for each column that need to be reported.

      Value of attribute mapsTo corresponds to column index (for “c0” it is “0”, for “c1” it is ”1”, etc).
      Value of node property is not used, so you may just put here some description or just set “value1” ,”value2”, “value3”, etc..

     

  3. Put all created prepared XML files to any specific folder on Notification Server
  4. Create new registry string value “HKEY_LOCAL_MACHINE\SOFTWARE\Altiris\Inventory\StandaloneCustomScripts” and set it to full path name to directory created in previous step
  5. Create new Standalone Package from Stand-alone Inventory Packages page (Settings > Discovery and Inventory > Inventory Solution > Stand-alone Inventory Packages)
    When registry key StandaloneCustomScripts is defined, scripts located under specified folder will be embedded to standalone package during package creation process, but it is required to select at least one pre-defined data class for collection - it is not allowed to create package without any data classes selected in UI
    Note: Altiris Log contains messages for each custom script, if format is invalid error is logged – search informational message “Importing custom inventory scripts” to review logs
  6. Execute created package on endpoints
  7. Custom data classes created in step 1 will be populated with collected data.

KNOWN ISSUES:
•    Script should return string like ‘<row c0=”field01” c1=”filed02”\> <row c0=”field11” c1=”filed12”\> <row c0=”field21” c1=”filed22”\>’
•    All values need to be XML escaped
•    Standalone package cannot include only custom scripts, at least one predefined data class should be selected for collection as well

GOOD TO KNOW:
Scripts may use predefined functions and constants (already embedded and existing in standalone package engine). List is available in Appendix A.
All custom functions used in script body should be located before they are called