Summary

Management groups are containers used to group devices and the software installed on those devices. Management groups are defined using configurable rules that look at various properties of the devices and their installed software, these are then evaluated to determine the group membership. This means that Management group membership adapts to changes to the devices and software in your environment.

Management groups are used by Tachyon to:

  • Determine the targets for questions, actions and reporting.
  • Determine user permissions for targeting on particular devices based on Management group membership.

In terms of permissions for determining how Tachyon users interact with the devices in your network, Management groups work alongside Instruction sets.

In Tachyon Platform 5.2, Management Groups are created in two different ways:

  • Rule based - the Management groups page lets you add, edit, delete and evaluate management groups that are based on rules - once created these appear in the Management groups page marked with an RB icon.
  • Direct based - these use scripts to create management groups by importing lists of devices using FQDN names only - once created these appear in the Management groups page marked with a DB icon.

    This type of Management group has no associated rules and cannot be edited and evaluated from the Management groups page.

Both types of Management group have the following properties:

  • Each device known to Tachyon can be assigned to any number of management groups, or be left unassigned. Devices not assigned to any management group will still be accessible, subject to permissions.
  • Roles can be associated with specific management groups, so that users with those roles will only be able to target the devices in their management groups.
  • Management groups can only contain devices, and they are completely independent of any other management group, even if they contain the same devices.
  • Each Management Group must have a unique name which is not case-sensitive.

On this page:

You need inventory connectors

Management groups use device data stored in an Inventory repository, which is populated using one or more inventory connectors, as described in Connectors page. This is sufficient for inventory-based applications like AppClarity, Application Migration, and Patch Success.

If you want client-based applications like Explorer, Experience and Guaranteed State to use the management groups, then you must add a Tachyon Connector, which synchronizes its own data with inventory data. The username and password you provide for the Connector must be a valid Tachyon user and belong to the Management Group Sync Initiators role. Please refer to the Tachyon connector page for more details. You only need to configure the connector, you do not need to schedule or run the Tachyon connector unless you also want to collect data from clients.

Creating direct-based management groups

Direct-based management groups are created using scripts. Two sample PowerShell scripts are provided.

  • Each script creates a new log file in the same folder, with file name format as <scriptname>_<ddMMyyyyhhmmss>.log which must be deleted manually.
  • If a management group already exists with the same name, the script will delete and recreate it, only with the new devices provided
  • If the file or collection includes a device that is not present in the Tachyon Inventory repository, then it is ignored, and logged.
  • After a successful run, the script triggers a management group sync

Prerequisites

  • User must have read/write permission in the folder where the PowerShell script is present
  • User must use UseCustomCredentials parameter if the current logged-in user does not have permission in Tachyon to create Management Groups
  • If Windows Task Scheduler is used to run a script, then the scheduled task should provide the current logged-in user

Create Direct-based management groups from a file

Click here to download - Create-DirectManagementGroupUsingFile.ps1

Create-DirectManagementGroupUsingFile.ps1
<#
.SYNOPSIS
1E Tachyon – Create Direct Management Group
Copyright © 1e Ltd 2021 - all rights reserved
http://www.1e.com

Version 1.5

Disclaimer
Your use of this software is at your sole risk. All software is provided "as-is", without any warranty, whether express or implied, of accuracy, completeness,
fitness for a particular purpose, title or non-infringement, and none of the software is supported or guaranteed by 1E. 1E shall not be liable for any damages
you may sustain by using this software, whether direct, indirect, special, incidental or consequential, even if it has been advised of the possibility of such
damages.

If you have an issue using this software, please ensure you are using an unmodified version before contacting 1E Support.


.DESCRIPTION
This script reads the Device FQDN list in files and creates Direct Membership Management Groups through SLA/Tachyon APIs. If the group does not exist
it is created and devices are added. If the group exists, the existing devices are deleted and new devices are added.


.PARAMETER TachyonApiBaseUrl
Mandatory parameter.  The header name used to access the Tachyon web service.  Should match the header listed in the IIS bindings on the Tachyon server.

.PARAMETER FolderPath
Mandatory parameter.  The name of the input folder which contains the files to be used in creating Direct Membership Management Groups. These files contain 
the list of devices to be used in creating Management Groups.  The File name should be same as the name of Name of Management Group. Also, the first line 
of the file should contain the description of Management Group to be created, from next line onwards every line contains the Device FQDN. 

.PARAMETER UseCustomCredentials
Optional switch.  If UseCustomCredentials is used, User will be prompted to enter the credentials, otherwise the script will use default credentials.


.EXAMPLE
.\Create-DirectManagementGroupUsingFile.ps1 -TachyonApiBaseUrl https://tachyon.lab.local -FolderPath C:\Temp\MgFolder

Scenario:
A Tachyon server is accessed using URL https://tachyon.lab.local/Tachyon using default credentials.  The files containing the Device FQDN list 
is in the directory C:\Temp\MyFolder.

.EXAMPLE
..\Create-DirectManagementGroupUsingFile.ps1 -TachyonApiBaseUrl https://tachyon.lab.local -FolderPath C:\Temp\MgFolder -UseCustomCredentials

Scenario:
A Tachyon server is accessed using URL https://tachyon.lab.local/Tachyon using different credentials other than current default credentials.  
The files containing the Device FQDN list is in the directory C:\Temp\MyFolder.

#>

param(
    [Parameter(Mandatory=$true, HelpMessage="Enter Tachyon API Base URL e.g. : https://tachyon.testlab.com")]
    [ValidateNotNullOrEmpty()]
    [string] $TachyonApiBaseUrl,

    [Parameter(Mandatory=$true, HelpMessage="Enter Folder Path which contains files containing Device FQDN list")]
    [ValidateNotNullOrEmpty()]
    [string] $FolderPath,

    [Parameter(Mandatory=$false, HelpMessage="To use Custom Credentials other than windows default credentials")]
    [Switch] $UseCustomCredentials
)

$ScriptVersion = "1.5" # Update the script version here

function Write-Log {

    [CmdletBinding()]
    Param(
          [parameter(Mandatory=$true)]
          [String]$Path,

          [parameter(Mandatory=$true)]
          [String]$Message,

          [parameter(Mandatory=$true)]
          [String]$Component,

          [Parameter(Mandatory=$true)]
          [ValidateSet("Debug", "Info", "Message", "Warning", "Error")]
          [String]$Type
    )

    switch ($Type) {
        "Info" { [int]$Type = 1 }
        "Warning" { [int]$Type = 2 }
        "Error" { [int]$Type = 3 }
        "Debug" { [int]$Type = 4 }
        "Message" { [int]$Type = 5 }
    }

    # Create a log entry
    $Content = "<![LOG[$Message]LOG]!>" +`
        "<time=`"$(Get-Date -Format "HH:mm:ss.ffffff")`" " +`
        "date=`"$(Get-Date -Format "M-d-yyyy")`" " +`
        "component=`"$Component`" " +`
        "context=`"$([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)`" " +`
        "type=`"$Type`" " +`
        "thread=`"$([Threading.Thread]::CurrentThread.ManagedThreadId)`" " +`
        "file=`"`">"

    try {
        # Write the line to the log file
        Add-Content -Path $Path -Value $Content
    }
    catch {
        Write-Host "User does not have access to write log at path $Path"
        Write-Host $Message
    }

    if ($Type -eq 1) {
        Write-Host $Message -ForegroundColor Yellow
    }

    if ($Type -eq 3) {
        Write-Host $Message -ForegroundColor Red
    }

    if ($Type -eq 5) {
        Write-Host $Message
    }
}

function Invoke-DirectMgApi{
    [CmdletBinding()]
    Param(
          [parameter(Mandatory=$true)]
          [String]$uri,

          [parameter(Mandatory=$true)]
          [String]$payload,

          [parameter(Mandatory=$false)]
          [System.Management.Automation.PSCredential]$credential
    )

    $hdrs = @{
        "Accept" = "application/json"
        "Content-type" = "application/json"
        "X-Tachyon-Consumer" = "Platform"
    }

    try {
        $stopwatchApi =  [system.diagnostics.stopwatch]::StartNew()

        $Content = "Invoking API"
        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message

        [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12

        if($credential){
            $response = Invoke-RestMethod -Method POST -Uri $uri -Body $payload -Credential $credential -Headers $hdrs
            $Content = "Response from API : $response"
            Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message
        }
        else {
            $response = Invoke-RestMethod -Method POST -Uri $uri -Body $payload -UseDefaultCredentials -Headers $hdrs
            $Content = "Response from API : $response"
            Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message
        }

        $stopwatchApi.Stop()
    
        $Content = "Time taken by API : $($stopwatchApi.Elapsed.TotalSeconds) seconds"
        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message   
    }
    catch {
        $err = $_

        $Content = "An error occured : $($err.Exception)"
        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Error

        $Content = "Error Details : $($err)"
        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug
    }    
}

# Get the Current Directory
$CurrentDirectory = $PSScriptRoot

if ($UseCustomCredentials -eq $true) {
    $cred = Get-Credential
}

$LogFilePath = Join-Path $PSScriptRoot "$($MyInvocation.MyCommand.Name)_$(Get-Date -Format ddMMyyyyHHmmss).log"

$Content = "************************************************"
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

$Content = "Starting script"
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

$Content = "************************************************"
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

$Content = "Running Script Version: " + $ScriptVersion
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

# Get the Current Directory

$Content = "Current Directory is " + $CurrentDirectory
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

$Content = "Tachyon API Base URL: " + $TachyonApiBaseUrl
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message

$Content = "Folder Path containing Device list files: " + $FolderPath
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message

$Content = "Verifying Folder Path : $FolderPath"
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

if (!(Test-Path $FolderPath)) {
    $Content = "Folder path does not exist : $FolderPath"
    Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Error

    exit
}

$Content = "Fetching all supported files from folder"
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug
$files = Get-ChildItem -Path $FolderPath -Filter *.txt

$Content = "Total Files in folder $FolderPath : $($files.Count)"
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

foreach($file in $files)
{
    $fileFullPath = $file.FullName

    $Content = "Reading File : $fileFullPath"
    Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message

    $stopwatchFileRead =  [system.diagnostics.stopwatch]::StartNew()
    
    $fqdnList = New-Object System.Collections.Generic.List[System.Object]

    foreach($line in [System.IO.File]::ReadLines($fileFullPath))
    {
        if($line -ne ""){
            $fqdnList.Add($line.Trim())
        }
    }

    if($fqdnList.Count -lt 2){
        $Content = "No device present in file"
        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Error
        
        Continue
    }

    #File name is Management Group Name
    $MGName = $file.BaseName

    #First line of the file is the Management Group Description
    $MgDescription = $fqdnList[0]
    
    #Removing the first line from collection as it's MG description
    $fqdnList.RemoveAt(0)

    $payload = ConvertTo-Json $fqdnList

    $stopwatchFileRead.Stop()

    $Content = "Time taken in reading file : $($stopwatchFileRead.Elapsed.TotalSeconds) seconds"
    Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug
    
    $Content = "Creating Management Group -"
    Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Info
    
    $Content = "  Name : $MGName"
    Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message
    
    $Content = "  Description : $MgDescription"
    Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message
    
    $Content = "  Total Devices in file : $($fqdnList.Count)"
    Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message
    
    #trimming any white space if any in the begining or end in url
    $TachyonApiBaseUrl = $TachyonApiBaseUrl.Trim()

    $uri = "$TachyonApiBaseUrl/admin/managementgroups/upload/$MGName/$MgDescription"

    $Content = "URI : $uri"
    Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

    Invoke-DirectMgApi -uri $uri -payload $payload -Credential $cred
    
}

$Content = "Complete"
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message

.\Create-DirectManagementGroupUsingFile.ps1 -TachyonApiBaseUrl https://tachyon.testlab.com -FolderPath C:\Temp\DeviceFolder -UseCustomCredentials
Parameter nameMandatoryDescription
TachyonApiBaseUrlYesTachyon Platform base URL, for example: https://tachyon.lab.local
FolderPathYesFolder path which contains files containing Device FQDN list
UseCustomCredentialsNoUse custom credentials (the script will prompt) otherwise current windows credentials will be used to call APIs.
  1. Create a folder which will contain text files to create Management Groups. This is the FolderPath passed as a parameter in PowerShell script.
  2. Create text files in the above folder with the name same as Management Group(e.g. ManagementGroupName.txt)
    • Enter Management Group Description in first line
    • Enter one or more Device FQDN from second line onwards, one device per line
  3. Optionally add more files if you want to create multiple management groups
  4. Execute the PowerShell script

To ensure all devices are present in the Tachyon Inventory repository, ensure you have configured a connector for the inventory source you are using to create your device lists.

Create Direct-based management groups from a Configuration Manager collection

Click here to download - Create-DirectManagementGroupUsingCmCollection.ps1

Create-DirectManagementGroupUsingCmCollection.ps1
<#
.SYNOPSIS
1E Tachyon – Create Direct Management Group
Copyright © 1e Ltd 2021 - all rights reserved
http://www.1e.com

Version 1.5

Disclaimer
Your use of this software is at your sole risk. All software is provided "as-is", without any warranty, whether express or implied, of accuracy, completeness,
fitness for a particular purpose, title or non-infringement, and none of the software is supported or guaranteed by 1E. 1E shall not be liable for any damages
you may sustain by using this software, whether direct, indirect, special, incidental or consequential, even if it has been advised of the possibility of such
damages.

If you have an issue using this software, please ensure you are using an unmodified version before contacting 1E Support.


.DESCRIPTION
This script reads the memberships of ConfigMgr Collections (Both Direct and Query based membership) and creates Direct Membership Management
Groups through SLA/Tachyon APIs. If the group does not exist it is created, and devices are added. If the group exists, the existing devices 
are deleted and new devices are added. The script is designed to run from the ConfigMgr server It queries WMI and gets the information 
necessary to connect to the ConfigMgr's site namespace.


.PARAMETER TachyonApiBaseUrl
Mandatory parameter.  The header name used to access the Tachyon web service.  Should match the header listed in the IIS bindings on the Tachyon server.

.PARAMETER FilePath
Mandatory parameter.  The name of the input file which contains the list of collections to be used in creating Direct Membership Management Groups.  Each line in file 
contains Collection Name, Management Group Name, and Management Group Description; all three values separated by a comma.
e.g.
Collection 1,Management Group 1, Management Group 1 Description
Collection 2,Management Group 2, Management Group 2 Description

.PARAMETER UseCustomCredentials
Optional switch.  If UseCustomCredentials is used, User will be prompted to enter the credentials, otherwise the script will use default credentials.

.EXAMPLE
.\Create-DirectManagementGroupUsingCmCollection.ps1 -TachyonApiBaseUrl https://tachyon.lab.local -FilePath C:\Temp\Collection.txt

Scenario:
A Tachyon server is accessed using URL https://tachyon.lab.local/Tachyon using default credentials.  The file containing the list of collections to process  
is in the location C:\Temp\Collection.txt.

.EXAMPLE
..\Create-DirectManagementGroupUsingCmCollection.ps1 -TachyonApiBaseUrl https://tachyon.lab.local -FilePath C:\Temp\Collection.txt -UseCustomCredentials

Scenario:
A Tachyon server is accessed using URL https://tachyon.lab.local/Tachyon using different credentials other than current default credentials.  
The file containing the list of collections to process is in the location C:\Temp\Collection.txt.

#>


param(
    [Parameter(Mandatory=$true, HelpMessage="Enter Tachyon API Base URL e.g. : https://tachyon.testlab.com")]
    [ValidateNotNullOrEmpty()]
    [string] $TachyonApiBaseUrl,

    [Parameter(Mandatory=$true, HelpMessage="Enter File Path which contains collection details in csv format. The file should contain Collection Name, Management Group Name, and Management Group Description")]
    [ValidateNotNullOrEmpty()]
    [string] $FilePath,

    [Parameter(Mandatory=$false, HelpMessage="To use Custom Credentials other than windows default credentials")]
    [Switch] $UseCustomCredentials
)

$ScriptVersion = "1.5" # Update the script version here

function Write-log {

    [CmdletBinding()]
    Param(
          [parameter(Mandatory=$true)]
          [String]$Path,

          [parameter(Mandatory=$true)]
          [String]$Message,

          [parameter(Mandatory=$true)]
          [String]$Component,

          [Parameter(Mandatory=$true)]
          [ValidateSet("Debug", "Info", "Message", "Warning", "Error")]
          [String]$Type
    )

    switch ($Type) {
        "Info" { [int]$Type = 1 }
        "Warning" { [int]$Type = 2 }
        "Error" { [int]$Type = 3 }
        "Debug" { [int]$Type = 4 }
        "Message" { [int]$Type = 5 }
    }

    # Create a log entry
    $Content = "<![LOG[$Message]LOG]!>" +`
        "<time=`"$(Get-Date -Format "HH:mm:ss.ffffff")`" " +`
        "date=`"$(Get-Date -Format "M-d-yyyy")`" " +`
        "component=`"$Component`" " +`
        "context=`"$([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)`" " +`
        "type=`"$Type`" " +`
        "thread=`"$([Threading.Thread]::CurrentThread.ManagedThreadId)`" " +`
        "file=`"`">"

    try {
        # Write the line to the log file
        Add-Content -Path $Path -Value $Content
    }
    catch {
        Write-Host "User does not have access to write log at path $Path" -ForegroundColor Yellow
        Write-Host $Message
    }

    if ($Type -eq 1) {
        Write-Host $Message -ForegroundColor Yellow
    }

    if ($Type -eq 3) {
        Write-Host $Message -ForegroundColor Red
    }

    if ($Type -eq 5) {
        Write-Host $Message
    }
}

function Invoke-DirectMgApi{
    [CmdletBinding()]
    Param(
          [parameter(Mandatory=$true)]
          [String]$uri,

          [parameter(Mandatory=$true)]
          [String]$payload,

          [parameter(Mandatory=$false)]
          [System.Management.Automation.PSCredential]$credential
    )

    $hdrs = @{
        "Accept" = "application/json"
        "Content-type" = "application/json"
        "X-Tachyon-Consumer" = "Platform"
    }

    try {
        $stopwatchApi =  [system.diagnostics.stopwatch]::StartNew()

        $Content = "Invoking API"
        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message

        [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12

        if($credential){
            $response = Invoke-RestMethod -Method POST -Uri $uri -Body $payload -Credential $credential -Headers $hdrs
            $Content = "Response from API : $response"
            Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message
        }
        else {
            $response = Invoke-RestMethod -Method POST -Uri $uri -Body $payload -UseDefaultCredentials -Headers $hdrs
            $Content = "Response from API : $response"
            Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message
        }

        $stopwatchApi.Stop()
    
        $Content = "Time taken by API : $($stopwatchApi.Elapsed.TotalSeconds) seconds"
        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message   
    }
    catch {
        $err = $_

        $Content = "An error occured : $($err.Exception)"
        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Error

        $Content = "Error Details : $($err)"
        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug
    }    
}

function Connect-ConfigMgrModule{
    try {
        # Load CM PowerShell Module

        if (-Not (Test-Path "HKLM:\SOFTWARE\Wow6432Node\Microsoft\ConfigMgr10\AdminUI")) {
            $Content = "Configuration Manager not found. Pleaes verify if the machine has Configuration Manager installed."
            Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Error
            exit
        }

        $CMConsolePath = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Wow6432Node\Microsoft\ConfigMgr10\AdminUI" | Select-Object -expandProperty AdminUILog).Replace("\AdminUILog\", "")
        if ($CMConsolePath) {
            Import-Module -Name "$CMConsolePath\bin\ConfigurationManager.psd1"
            $Content = "Loaded ConfigurationManager.psd1 module"
            Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug
        }
        else {
            $Content = "ConfigurationManager.psd1 module not found. Pleaes verify if the machine has Configuration Manager installed."
            Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Error
            exit
        }
        
        # Get the CM Site Code
        $CMSiteCode = Get-WMIObject -Namespace root\sms -Class SMS_ProviderLocation | Select-Object -expandproperty SiteCode

        if ($CMSiteCode -eq "") { 
            $Content = "Sitecode could not be determined."
            Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Error
            exit
        }

        $Content = "ConfigMgr Site Code: " + $CMSiteCode
        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message

        $CMLocation = $CMSiteCode + ":"

        $Content = "Setting Location : $CMLocation"
        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

        Push-Location

        Set-Location -Path $CMLocation
    }
    catch {
        $err = $_

        $Content = "An error occured while loading configuration manager module : $($err.Exception)"
        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Error

        $Content = "Error Details : $($err)"
        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

        exit
    }

    
}

function Read-ConfigMgrDeviceCollection{
    [CmdletBinding()]
    Param(
          [parameter(Mandatory=$true)]
          [hashtable]$collectionList
    )

    try {
        $stopwatch =  [system.diagnostics.stopwatch]::StartNew()

        $arrCMCollList = Get-CMDeviceCollection | Select-Object -Property CollectionID,Name
        ForEach ($CMCollection IN $arrCMCollList){
            $CMCollName = $CMCollection.Name
            
            $Content = "Retrieved Collection Name from ConfigMgr: " + $CMCollName
            Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

            $CMCollId = $CMCollection.CollectionID

            If ($collectionList.ContainsKey($CMCollName)){

                $arrCollectionMembership = Get-CMCollectionMember -CollectionId $CMCollID | Select-Object -expandProperty Name
                If ($null -ne $arrCollectionMembership){
                    $Content = "Fetching Devices from Collection : " + $CMCollName
                    Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message

                    $MgName = $collectionList["$CMCollName"][0]
                    $MgDescription = $collectionList["$CMCollName"][1]
                    
                    #Create File to save the device list, which later will be used to create MG
                    $MGFileName = $MgName + ".txt"
                    $MGFilePath = Join-Path $FolderPath $MGFileName
                    if (!(Test-Path $MGFilePath)){
                        $Content = New-Item -itemType File -Path $FolderPath -Name $MGFileName
                        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

                        $Content = "Created file $MGFilePath"
                        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

                        Add-Content -Path "$MGFilePath" -Value "$MgDescription"

                        $Content = "Added description $MgDescription"
                        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug
                    }
                    
                    ForEach ($CollMember IN $arrCollectionMembership){
                        $deviceDetails = Get-CMDevice -Name $CollMember -Resource | Select-Object Name,FullDomainName
                        $deviceFullName = $deviceDetails.Name + "." + $deviceDetails.FullDomainName
                        
                        $Content = "Adding device: " + $deviceFullName + " to MG File: " + $MgName
                        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

                        Add-Content -Path "$MGFilePath" -Value "$deviceFullName"
                    }
                }

            }
        }

        $stopwatch.Stop()

        $Content = "Time taken in reading devices from Collection : $($stopwatch.Elapsed.TotalSeconds) seconds"
        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message
        
        Pop-Location

        $Content = "Update location back to local drive"
        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

        $Content = "**********************"
        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message                                        
    }
    catch {
        $err = $_

        $Content = "An error occured while fetching devices : $($err.Exception)"
        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Error

        $Content = "Error Details : $($err)"
        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

        exit
    }

   
}

# Get the Current Directory
$CurrentDirectory = $PSScriptRoot

#Temp Folder to contain list of devices which will be used to create MG
$MGFolderName = "MGDeviceList"
$FolderPath = Join-Path $CurrentDirectory $MGFolderName

if ($UseCustomCredentials -eq $true) {
    $cred = Get-Credential
}


$LogFilePath = Join-Path $CurrentDirectory "$($MyInvocation.MyCommand.Name)_$(Get-Date -Format ddMMyyyyHHmmss).log"


$Content = "************************************************"
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

$Content = "Starting Script"
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

$Content = "************************************************"
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

$Content = "Running Script Version: " + $ScriptVersion
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

$Content = "Current Directory is: " + $CurrentDirectory
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

$Content = "Tachyon API Base URL: " + $TachyonApiBaseUrl
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message

$Content = "File Path containing CM Collection list: " + $FilePath
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message

$Content = "Temp Folder Path to save Device List: " + $FolderPath
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message


$Content = "Verifying File Path : $FilePath"
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

if (!(Test-Path $FilePath)) {
    $Content = "File path does not exist : $FilePath"
    Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Error

    exit
}

try {
    if (!(Test-Path $FolderPath)) {
        $Content = "Creating temp folder : $FolderPath"
        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug
    
        $Content = New-Item -Path "$CurrentDirectory" -Name $MGFolderName -ItemType "directory"
        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug
    }
    else{
        $Content = "Deleting existing MG files from $FolderPath"
        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug
    
        # Delete Collection Membership List Files
        Remove-Item -Path "$FolderPath\*.*"
    }
}
catch {
    $Content = "User does not have permission to create : $FolderPath"
    Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Error

    exit
}

# Read Collection Details from File
$Content = "Reading collection details from $FilePath"
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message

$collectionList = @{}

foreach($line in [System.IO.File]::ReadLines($FilePath))
{
    if($line -ne ""){
        $collectionDetails = $line.Split(",")
        if($collectionDetails.Count -lt 3){
            $Content = "Input data not in correct format. It should contain <CollectionName>,<MGName>,<MGDescription>"
            Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Error
            exit
        }
        $collectionList.Add($collectionDetails[0],@($collectionDetails[1],$collectionDetails[2]))
    }
}

if($collectionList.Count -lt 1){
    $Content = "No collection details present in file"
    Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Error
    
    exit
}

#Loading Config Manager Powershell Modules
Connect-ConfigMgrModule

#Read Device Collections from Config Manager and prepare device list in temp folder which will be used to create 
Read-ConfigMgrDeviceCollection -collectionList $collectionList

$Content = "Verifying Folder Path : $FolderPath"
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

if (!(Test-Path $FolderPath)) {
    $Content = "Folder path does not exist : $FolderPath"
    Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Error

    exit
}

$Content = "Fetching all files from folder"
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug
$files = Get-ChildItem -Path $FolderPath -Filter *.txt


$Content = "Total Files in folder $FolderPath : $($files.Count)"
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

foreach($file in $files)
{
    $fileFullPath = $file.FullName

    $Content = "Reading File : $fileFullPath"
    Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message

    $stopwatchFileRead =  [system.diagnostics.stopwatch]::StartNew()

    $fqdnList = New-Object System.Collections.Generic.List[System.Object]

    foreach($line in [System.IO.File]::ReadLines($fileFullPath))
    {
        if($line -ne ""){
            $fqdnList.Add($line)
        }
    }

    if($fqdnList.Count -lt 2){
        $Content = "No device present in file"
        Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Error
        
        Continue
    }

    #File name is Management Group Name
    $MGName = $file.BaseName

    #First line of the file is the Management Group Description
    $MgDescription = $fqdnList[0]
    
    #Removing the first line from collection as it's MG description
    $fqdnList.RemoveAt(0)

    $payload = ConvertTo-Json $fqdnList

    $stopwatchFileRead.Stop()

    $Content = "Time taken in reading file : $($stopwatchFileRead.Elapsed.TotalSeconds) seconds"
    Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug
   
    $Content = "Creating Management Group -"
    Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Info
    
    $Content = "  Name : $MGName"
    Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message
    
    $Content = "  Description : $MgDescription"
    Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message
    
    $Content = "  Total Devices in file : $($fqdnList.Count)"
    Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message
    
    #trimming any white space if any in the begining or end in url
    $TachyonApiBaseUrl = $TachyonApiBaseUrl.Trim()

    $uri = "$TachyonApiBaseUrl/admin/managementgroups/upload/$MGName/$MgDescription"

    $Content = "URI : $uri"
    Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Debug

    Invoke-DirectMgApi -uri $uri -payload $payload -Credential $cred
}

$Content = "Complete"
Write-Log -Path $LogFilePath -Message $Content -Component $MyInvocation.MyCommand.Name -Type Message

.\Create-DirectManagementGroupUsingCmCollection.ps1 -TachyonApiBaseUrl https://tachyon.testlab.com -FilePath C:\Temp\Collection.txt -UseCustomCredentials
Parameter nameMandatoryDescription
TachyonApiBaseUrlYesTachyon Platform base URL, for example: https://tachyon.lab.local
FilePathYesFile path which contains details of CM Collections
UseCustomCredentialsNoUse custom credentials (the script will prompt) otherwise current windows credentials will be used to call APIs.
  1. Create a text file which will be passed as a parameter in PowerShell script.
  2. In the file enter the following as a comma separated single line: Collection name, Management Group Name, Management Group Description
  3. Optionally enter more lines in the same format if you want to create multiple management groups 
  4. Execute the PowerShell script

This script is designed to be run on the Configuration Manager Site server.

To ensure all CM devices are present in the Tachyon Inventory repository, ensure you have a System Center Configuration Manager connector and run its Data Sync action to populate the repository.

Working with direct-based management groups

Given the information provided in Creating direct-based management groups we can now give an example of how direct-based management groups can be added.

Before adding the direct-based management groups

In our system we already have one rule-based management group, as shown in the picture opposite. Here you can see the green RB icon before the management group name link, we'll use this later to contrast with how the direct-based management groups appear.

The device files

We've created a C:\Temp\DeviceFolder folder and added two files, Servers.txt and Workstations.txt that contain a list of device FQDN on separate lines.

Running the script to populate the direct-based management groups

With the device files in place, in our example we run the Create-DirectManagementGroupUsingFile.ps1 file with the following command-line:

.\Create-DirectManagementGroupUsingCmCollection.ps1 -TachyonApiBaseUrl https://tachyon.acme.local -FilePath C:\Temp\DeviceFolder.txt

Where the TachyonApiBaseUrl is set to our example instance of  https://tachyon.acme.local  and the -FolderPath is set to the C:\Temp\DeviceFolder we set up earlier. We don't bother with the UseCustomCredentials setting as the  account we are running the script with has administrator permissions in Tachyon.

Checking the log file for Create-DirectManagementGroupUsingFile.ps1

After running the script you will find a log file is created in the same directory where the  Create-DirectManagementGroupUsingFile.ps1 is located. In our example we can see that the script completed without errors.

The reports for creating and enabling the direct-based management groups

When the direct-based management groups are added to Tachyon some reports will run to enable the management groups to be used.

If more than one direct-based management groups are being added you will see two Management Group Evaluation reports run on the default Inventory repository. You will also see an additional Management Group Evaluation report run on each additional non-default inventory repositories you have in your system.

If you have Application Migration installed you will also see two Application Migration Consolidation reports run on the default ApplicationMigration repository.

In our example we have Application Migration installed, so we see four reports run when the DB management groups are added. Two Management Group Evaluation reports and two Application Migration Consolidation reports, as can be seen in the picture opposite.

The direct-based management groups added

After running the script two new direct-based management groups get added: Servers and Workstations. The new management groups have a red DB icon to show these are direct-based management groups.

You can drill-down to see the details of a management group by clicking the Name link.

Clicking on the Servers management group name link displayes the details for that management group. You can click on the number link in the Devices column to open the Inventory application, shown a list of devices in the management group.

The Inventory→Hardware Inventory page is displayed with the management group selector set to the name of the management group, in this case Servers. As you can see this list contains all of the devices that were listed in the Servers.txt devices file we showed earlier.

Working with rule-based management groups

Rule-based Management groups are defined and maintained in the SettingsPermissions→Management groups page, using device inventory data gathered from data sources by connectors and then use those management groups to control the application of instructions in Tachyon applications.

Creating a rule-based management group

To create a rule-based management group:

  1. Navigate to the Settings→Permissions→Management groups page.
  2. Click the Add button to display the Add management group popup.
  3. Enter a suitable Name for the management group. For example Devices.
  4. Add a Description, it's a good idea to use a description that provides an outline of the rules that are used to populate the management group. For example Device Computer Name Contains ACME.
  5. To add each rule:
    1. Click on the + button. The first one is already added, all you need to do is fill out the parts of the rule.
    2. First you select the rule name using the left dropdown menu. For example, Device Computer Name.
    3. You then select the condition. For example Contains.
    4. To complete the rule you then set the value. For example ACME.
  6. Repeat step 5 for each rule you want to define.
  7. When you have more than one rule added you can:
    1. Use the gripper icon at the right-hand end of the rule to change the order the rules are applied by dragging the rule to a new place in the list.
    2. Change the conjunction operator at the left-hand end of the rule to select between AND and OR.
  8. When you have finished adding the rules you need to decide whether you want the management group membership to be evaluated immediately on adding the management group. If you are just adding one management group it makes sense to check the Evaluate rules immediately checkbox. If you are adding a number of management groups it may be a good idea to leave the checkbox unchecked for all of them except for the last one.
  9. If you check Evaluate rules immediately and there is more than one inventory repository an additional control will be displayed prompting you to select which repository you want to evaluate the management group rules against.
  10. When you've finished making all the settings click the Add button to add the management group definition.

The management group will be added to the Management groups table.

If you selected to evaluate rules immediately the rules you set for the management group will be evaluated against the selected inventory repository.

To check how many devices are in the management group click on the management group name link in the Name column.

The picture opposite shows the details for the Devices management group showing that it contains 11 devices.

Once the management group rules have been evaluated, you should then be able to check the devices in Explorer contained in the group using the Explorer→Devices→Table page. The picture opposite shows the devices table with the Management group filter set to Devices.

Editing a rule-based management group

To edit an existing rule-based management group:

  1. Navigate to the Settings→Permissions→Management groups page.
  2. In the Management groups table, locate the management group you want to edit and check the checkbox at the left hand end of its row.
  3. Click the Edit button to display the Edit management group popup for the selected management group.
  4. Here you can edit the Name, Description and Rules that define the management group.
  5. When you've finished editing, before you click the Save button you can check the Evaluate rules immediately checkbox, this will enable any modifications you've made to the rules take effect right away. If you don't check the box the rules won's be run and you'll be able to evaluate the management groups later.

Deleting a management group

The following applies to rule-based and direct-based management groups. 

To delete an existing management group:

  1. Navigate to the Settings→Permissions→Management groups page.
  2. In the Management groups table, locate the management group you want to delete and check the checkbox at the left hand end of its row.
  3. Click the Delete button. This displays the Delete management group popup.
  4. Here you are asked in you want to proceed with the delete process. Click the Yes, delete management group button to confirm the deletion or No to cancel.

Evaluating management group membership

You can select to evaluate the management groups at any time. Doing this will process 

  1. Navigate to the Settings→Permissions→Management groups page.
  2. Click the Evaluate button.
  3. If there is only one inventory repository the evaluation will be queued immediately. If there is more than one inventory repository the Evaluate management groups popup will be displayed and you will need to select a Repository then click the Evaluate button before the evaluation is queued.
  4. When an evaluation is queued you will see a Management Group Evaluation action appear on the Settings→Monitoring→Process log page. From there you can view the progress of the evaluation.
  5. When this action has run the Explorer application will reflect any changes that have been made to the management group memberships.

Management group rules and conditions

Each row in the Rules section is laid out as follows:

ConjunctionRule NameOperandValueDeleteGripper

When there is more than one rule this field determines how it is evaluated with the other rules. This may be one of:

ConjunctionDescription
ANDThis rule must be satisfied as well as any other rules.
OREither this rule must be satisfied or any other rules.

Determines the type of information checked when evaluating the rule. For example selecting Device Computer Name will specify checking the set value against the information held internally for each device's computer name using the selected operand.

Please refer to List of available management group rules for a list of the options.

How the value is compared against the type of information.

This may be one of the following:

OperandDescription
ContainsThe text or number in the value must appear in the device information.
Not ContainsThe text or number in the value must not appear in the device information.
EqualsThe text or number in the value must be exactly equal to the device information.
Not EqualsThe text or number in the value must not be equal to the device information.
Is NullThe device information must be Null.
Not NullThe device information must not be Null.

The value field is either a string or numeric value, depending on the chosen rule name.

This field contains an icon that lets you delete the rule.This field lets you grab the rule and change its order where there is more than one rule.

List of available management group rules


Rules used to create Management Groups, and which connectors that provide the data to support the rules. For details of how to create and use Management Groups, please refer to Management groups page.

The number of rules that a single Management Group can contain is variable because of many factors including SQL Server version, server configuration and rule type used. 1E recommends not exceeding 10,000 rules per rule-based Management Group.

Rule nameDescriptionSCCMServiceNowTachyonOracleLMSBigFixBigFixInvIntunevCenterWSUS
Device ADSite NameAD Site the device is connected to.(tick)(tick)






Device Assigned Cores

Maximum number of assigned cores for the device.

Derived from 

(tick)(tick)(tick)(tick)(tick)

(tick)
Device Classification

Classification of the device. For example, Test, Production or Development.

Production is the default.
(tick)(tick)
(tick)




Device Computer NameHostname of the computer.(tick)(tick)(tick)(tick)(tick)(tick)(tick)(tick)(tick)
Device Criticality

By default, Device Criticality is set as one of the following, as described in Tachyon Explorer 5.2: Using Device Criticality.

  • Undefined
  • Non-critical
  • Low
  • Medium
  • High
  • Critical.
(tick)(tick)(tick)(tick)(tick)(tick)(tick)(tick)(tick)
Device Domain NameDomain the device is installed on.(tick)(tick)(tick)

(tick)


Device Inventory dateDate that the device was last updated.(tick)(tick)(tick)(tick)

(tick)(tick)(tick)
Device Matched Device TypeNormalized device type based on chassis type. For example Desktop.(tick)(tick)(tick)(tick)(tick)
(tick)(tick)(tick)
Device Matched FamilyNormalized family of the device. For example, Aspire.(tick)(tick)(tick)(tick)(tick)

(tick)
Device Matched ModelNormalized model of the device. For example, A30.(tick)(tick)(tick)(tick)(tick)
(tick)(tick)(tick)
Device Matched Socket countNormalized socket count of the device. For example, 1.(tick)(tick)(tick)(tick)(tick)
(tick)(tick)(tick)
Device Matched VendorNormalized vendor name of the device. For example, Acer Inc..(tick)(tick)(tick)(tick)(tick)
(tick)(tick)(tick)
Device Netbios Domain nameNetBIOS version of the device's domain name.(tick)(tick)(tick)





Device Netbios NameNetBIOS version of the device name.(tick)(tick)(tick)



(tick)
Device OSThe normalized product title of the OS that is running on the device.(tick)(tick)(tick)
(tick)(tick)
(tick)
Device Purchase dateDate that the device was purchased.(tick)(tick)






Device SerialSerial number of the computer.(tick)(tick)


(tick)(tick)

Device User Primary Username

The primary user of the device. 

(tick)
(tick)





OU Name (Deprecated)

Name of the OU that the device is in. For example Sales.

All OUs with the same name will be used, therefore the OU Path rule should be used instead. The OU Name rule is deprecated and should be re-defined using OU Path.

This rule is deprecated, which means it will continue to work until it is removed in a future version of Tachyon.

(tick)(tick)






OU Path

The name or path of the OU location in the AD hierarchy, using pipe | as the delimiter.

For example, to get all the computers in OU=Sales, OU=Workstations, DC=acme, DC=local you can either specify Sales or - if there is more than one OU called Sales in the AD structure - specify the whole path acme.local|Workstations|Sales. Note that the DC and OU parts of a distinguished name are treated differently.

(tick)(tick)






Processor Matched Chip Module CountNormalized chip module count of the processor. For example, 1.(tick)(tick)(tick)(tick)(tick)



Processor Matched Core CountNormalized core count of the processor. For example, 2.(tick)(tick)(tick)(tick)(tick)

(tick)
Processor Matched FamilyNormalized family name of the processor. For example, Athlon 64 X2.(tick)(tick)(tick)(tick)(tick)

(tick)
Processor Matched ModelNormalized model name of the processor. For example, 3250e.(tick)(tick)(tick)(tick)(tick)

(tick)
Processor Matched Processor TypeNormalized type of the processor. For example, Desktop.(tick)(tick)(tick)(tick)(tick)

(tick)
Processor Matched Release DateNormalized release date of the processor. For example, 31-03-2008.(tick)(tick)(tick)(tick)(tick)

(tick)
Processor Matched Speed M HzNormalized speed of the processor. For example, 2.100.(tick)(tick)(tick)(tick)(tick)

(tick)
Processor Matched Threads per CoreNormalized threads per core of the processor. For example, 1.(tick)(tick)(tick)(tick)(tick)

(tick)
Processor Matched VendorNormalized vendor name of the processor. For example, Advanced Micro Devices, Inc.(tick)(tick)(tick)(tick)(tick)

(tick)
Product Catalog Colloquial Version

Software colloquial version contained in the inventory source. For example, 2012.

This will usually be blank.
(tick)(tick)


(tick)(tick)

Product Catalog Edition

Software edition contained in the inventory source. For example, Standard.

This will usually be blank in SCCM unless the relevant MOF extensions have been installed.
(tick)(tick)(tick)

(tick)(tick)

Product Catalog Is Partial Version MatchedFlag that indicates whether the software title was partial matched or not (TRUE/1) or not (FALSE/0).(tick)(tick)(tick)(tick)(tick)(tick)(tick)

Product Catalog Matched Colloquial VersionNormalized software colloquial version. For example, 2016.(tick)(tick)(tick)(tick)(tick)(tick)(tick)

Product Catalog Matched EditionNormalized software edition. For example, Standard.(tick)(tick)(tick)(tick)(tick)(tick)(tick)

Product Catalog Matched End of SupportNormalized software end of support date that of that version. For example, 31-10-2008.(tick)(tick)(tick)(tick)(tick)(tick)(tick)

Product Catalog Matched is BundleFlag indicating whether the normalized software is a bundle (TRUE/1) or not (FALSE/0).(tick)(tick)(tick)(tick)(tick)(tick)(tick)

Product Catalog Matched Is License RequiredFlag indicating whether that normalized software title requires a license (TRUE/1) or not (FALSE/0).(tick)(tick)(tick)(tick)(tick)(tick)(tick)

Product Catalog Matched Release DateNormalized software release date of that version. For example, 31-10-2008.(tick)(tick)(tick)(tick)(tick)(tick)(tick)

Product Catalog Matched TitleNormalized software title. For example, Office.(tick)(tick)(tick)(tick)(tick)(tick)(tick)

Product Catalog Matched VendorNormalized software vendor name. For example, Microsoft Corporation.(tick)(tick)(tick)(tick)(tick)(tick)(tick)

Product Catalog Matched VersionNormalized software version. For example, 10.2.233.(tick)(tick)(tick)(tick)(tick)(tick)(tick)

Product Catalog TitleSoftware title contained in the inventory source. For example, Office Standard en_pack.(tick)(tick)(tick)(tick)(tick)(tick)(tick)

Product Catalog UN Standard Product Service CodeUNSPC code of the normalized software title.(tick)(tick)(tick)(tick)(tick)(tick)(tick)

Product Catalog VendorSoftware vendor name contained in the inventory source. For example, Microsoft.(tick)(tick)(tick)
(tick)(tick)(tick)

Product Catalog VersionSoftware version number contained in the inventory source. For example, 10.2.233.(tick)(tick)(tick)(tick)(tick)(tick)(tick)

Product Install DateDate that software installation was installed according to the inventory source.(tick)
(tick)





Product Instance NameInstance name if used by a product, for example MSSQLSERVER for SQL Server.(tick)(tick)(tick)(tick)(tick)



Product Last Used dateDate that software installation was last run according to the inventory source.(tick)
(tick)





Product Usage CategoryUsage category assigned to a specific installation of a  normalized software title. Potential categories are:
- Used
- Unused
- Rarely used
- Unreported
(tick)(tick)(tick)(tick)