SCOM Management Agent PowerShell Properties Discovery

SCOM.Management.Agent.Class.PowerShell.Properties.Discovery (Discovery)

Element properties:

TargetSCOM.Management.Agent.Class
EnabledTrue
Frequency86393
RemotableFalse

Object Discovery Details:

Discovered Classes and their attribuets:
  • SCOM.Management.Agent.Class
    • AgentVersion
    • UpdateRollup
    • ADIntEnabled
    • ManagementGroups
    • OMSWorkspaces
    • ProxyURL
    • PSVersion
    • CLRVersion
    • PrimaryMS
    • FailoverList
    • ActionAccount
    • OSVersion
    • InstallPath
    • CertLoaded
    • CertExpires
    • ThumbPrint
    • CertIssuer
    • IP
    • Connection

Member Modules:

ID Module Type TypeId RunAs 
DS DataSource Microsoft.Windows.TimedPowerShell.DiscoveryProvider Default

Source Code:

<Discovery ID="SCOM.Management.Agent.Class.PowerShell.Properties.Discovery" Enabled="true" Target="SCOM.Management.Agent.Class" ConfirmDelivery="false" Remotable="true" Priority="Normal">
<Category>Discovery</Category>
<DiscoveryTypes>
<DiscoveryClass TypeID="SCOM.Management.Agent.Class">
<Property PropertyID="AgentVersion"/>
<Property PropertyID="UpdateRollup"/>
<Property PropertyID="ADIntEnabled"/>
<Property PropertyID="ManagementGroups"/>
<Property PropertyID="OMSWorkspaces"/>
<Property PropertyID="ProxyURL"/>
<Property PropertyID="PSVersion"/>
<Property PropertyID="CLRVersion"/>
<Property PropertyID="PrimaryMS"/>
<Property PropertyID="FailoverList"/>
<Property PropertyID="ActionAccount"/>
<Property PropertyID="OSVersion"/>
<Property PropertyID="InstallPath"/>
<Property PropertyID="CertLoaded"/>
<Property PropertyID="CertExpires"/>
<Property PropertyID="ThumbPrint"/>
<Property PropertyID="CertIssuer"/>
<Property PropertyID="IP"/>
<Property PropertyID="Connection"/>
</DiscoveryClass>
</DiscoveryTypes>
<DataSource ID="DS" TypeID="Windows!Microsoft.Windows.TimedPowerShell.DiscoveryProvider">
<IntervalSeconds>86393</IntervalSeconds>
<SyncTime/>
<ScriptName>SCOM.Management.Agent.Class.PowerShell.Properties.Discovery.ps1</ScriptName>
<ScriptBody><Script>
#=================================================================================
# Script to gather agent properties via PowerShell
#
# Author: Kevin Holman
# v1.4
#=================================================================================
param($SourceId,$ManagedEntityId,$ComputerName,$MGName,[string]$IP)


# Manual Testing section - put stuff here for manually testing script - typically parameters:
#=================================================================================
# $SourceId = '{00000000-0000-0000-0000-000000000000}'
# $ManagedEntityId = '{00000000-0000-0000-0000-000000000000}'
# $Computername = 'server.domain.com'
# $MGName = 'SCOMA'
# $IP = '123.123.123.123'
#=================================================================================


# Constants section - modify stuff here:
#=================================================================================
# Assign script name variable for use in event logging
$ScriptName = "SCOM.Management.Agent.Class.PowerShell.Properties.Discovery.ps1"
$EventID = "1006"

#SCOM Management Servers or Gateways that we wish to test the port availability to using FQDN seperated by a comma such as "scom1.opsmgr.net","scom2.opsmgr.net","scom3.opsmgr.net"
[array]$Parents = ""
#=================================================================================


# Starting Script section - All scripts get this
#=================================================================================
# Gather the start time of the script
$StartTime = Get-Date
#Set variable to be used in logging events
$whoami = whoami
# Load MOMScript API
$momapi = New-Object -comObject MOM.ScriptAPI
#Log script event that we are starting task
$momapi.LogScriptEvent($ScriptName,$EventID,0,"`nScript is starting. `nManagement Group: ($MGName). `nRunning as ($whoami).")
#=================================================================================


# Discovery Script section
#=================================================================================
# Load SCOM Discovery module
$DiscoveryData = $momapi.CreateDiscoveryData(0, $SourceId, $ManagedEntityId)
#=================================================================================


# Begin MAIN script section
#=================================================================================
#Check and see if OS is Nano server for use later where we must take different actions for Nano servers
$isNano = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Server\ServerLevels"
$isNano = $isNano.NanoServer
if($isNano -ne $null)
{
$isNano = $true
}
else
{
$isNano = $false
}

# Get SCOM Agent Path Section
#=======================================================================
$SCOMRegKey = "HKLM:\SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Setup"
$SCOMAgentPath = (Get-ItemProperty $SCOMRegKey).InstallDirectory
$SCOMAgentPath = $SCOMAgentPath.TrimEnd("\")
#=======================================================================

# Get SCOM Agent Version Section
#=======================================================================
$SCOMAgentVersionFile = Get-Item $SCOMAgentPath\Tools\TMF\OMAgentTraceTMFVer.Dll
$SCOMAgentVersion = $SCOMAgentVersionFile.VersionInfo.FileVersion
$SCOMAgentVersionSplit = $SCOMAgentVersion.Split(".")
[int]$MajorSCOMAgentVersion = $SCOMAgentVersionSplit[0]

[string]$SCOMAgentURVersion = switch($SCOMAgentVersion)
{
# SCOM 2012
"7.1.10184.0" {"2012 R2 RTM"}
"7.1.10195.0" {"2012 R2 UR2"}
"7.1.10204.0" {"2012 R2 UR3"}
"7.1.10211.0" {"2012 R2 UR4"}
"7.1.10213.0" {"2012 R2 UR5"}
"7.1.10218.0" {"2012 R2 UR6"}
"7.1.10229.0" {"2012 R2 UR7"}
"7.1.10241.0" {"2012 R2 UR8"}
"7.1.10268.0" {"2012 R2 UR9"}
"7.1.10285.0" {"2012 R2 UR11"}
"7.1.10292.0" {"2012 R2 UR12"}
"7.1.10302.0" {"2012 R2 UR13"}
"7.1.10305.0" {"2012 R2 UR14"}

# SCOM 2016
"8.0.10918.0" {"2016 RTM"}
"8.0.10931.0" {"2016 UR1"}
"8.0.10949.0" {"2016 UR2"}
"8.0.10970.0" {"2016 UR3"}
"8.0.10977.0" {"2016 UR4"}
"8.0.10990.0" {"2016 UR5"}
"8.0.11004.0" {"2016 UR6"}
"8.0.11025.0" {"2016 UR7"}
"8.0.11037.0" {"2016 UR8"}
"8.0.11049.0" {"2016 UR9"}

# SEMI ANNUAL Channel
"8.0.13053.0" {"1801"}
"8.0.13067.0" {"1807"}

# SCOM 2019
"10.19.10003.0" {"2019 TP"}
"10.19.10014.0" {"2019 RTM"}
"10.19.10140.0" {"2019 UR1"}

# If nothing else found then default to version number
default {$SCOMAgentVersion}
}
#=======================================================================

# Load Agent Scripting Module
#=======================================================================
$AgentCfg = New-Object -ComObject "AgentConfigManager.MgmtSvcCfg"
#=======================================================================

# Get Agent Management groups section
#=======================================================================
#Get management groups
$MGs=$AgentCfg.GetManagementGroups()

#Loop through each and create a comma seperated list
FOREACH ($MG in $MGs)
{
$MGList=$MGList + $MG.managementGroupName + ", "
}
$MGlist=$MGlist.TrimEnd(", ")
#=======================================================================

# Get Agent OMS Workspaces section
#=======================================================================
# This section depends on AgentConfigManager.MgmtSvcCfg object in previous section
[string]$OMSList=''
# Agent might not support OMS
$AgentSupportsOMS = $AgentCfg | Get-Member -Name 'GetCloudWorkspaces'
IF (!$AgentSupportsOMS)
{
#This agent version does not support Cloud Workspaces.
}
ELSE
{
$OMSWorkSpaces = $AgentCfg.GetCloudWorkspaces()
FOREACH ($OMSWorkSpace in $OMSWorkSpaces)
{
$OMSList = $OMSList + $OMSWorkspace.workspaceId + ", "
}
IF ($OMSList)
{
$OMSList = $OMSList.TrimEnd(", ")
}

#Get ProxyURL
[string]$ProxyURL = $AgentCfg.proxyUrl
}
#=======================================================================

# Get Agent AD Integration Setting
#=======================================================================
# This section depends on AgentConfigManager.MgmtSvcCfg object in previous section
# Check Agent version for 2012 or a later version as these use different commands
IF ($MajorSCOMAgentVersion -lt 8)
{
# Assume SCOM 2012 agent
$ADIntEnabled = $AgentCfg.GetActiveDirectoryIntegrationEnabled()
}
Else
{
# Assume SCOM 2016 agent or later
$ADIntEnabled = $AgentCfg.ActiveDirectoryIntegrationEnabled
}
#=======================================================================

# Get PowerShell Version section
#=======================================================================
$PSVer = $PSVersionTable.PSVersion
[string]$PSMajor = $PSVer.Major
[string]$PSMinor = $PSVer.Minor
$PSVersion = $PSMajor + "." + $PSMinor
#=======================================================================

# Get PowerShell CLR Version section
#=======================================================================
$CLRVer = $PSVersionTable.CLRVersion
[string]$CLRMajor = $CLRVer.Major
[string]$CLRMinor = $CLRVer.Minor
$CLRVersion = $CLRMajor + "." + $CLRMinor
#=======================================================================

# Get Agent Assignments section
#======================================================================
$FilePath = "$SCOMAgentPath\Health Service State\Connector Configuration Cache\$MGName\OpsMgrConnector.Config.xml"

IF (Test-Path -Path $FilePath)
{
[xml]$ConfigFileXML = Get-Content -Path $FilePath

#Get Primary MS
$PrimaryArr = $ConfigFileXML.Message.State.Parents.Added.Item | Where-Object {$_.IsPrimary -eq "True"}
$PrimaryMS = $PrimaryArr.AuthenticationName

#Get list of Secondary MS
$SecondaryArr = $ConfigFileXML.Message.State.Parents.Added.Item | Where-Object {$_.IsPrimary -eq "False"}
[string]$SecondaryMSList = @()
FOREACH ($SecondaryXML in $SecondaryArr)
{
$SecondaryMS = $SecondaryXML.AuthenticationName
$SecondaryMSList = $SecondaryMSList + $SecondaryMS + ", "
}
$FailoverList = $SecondaryMSList.TrimEnd(", ")
}
ELSE
{
#Log script event that we cannot find config file
$momapi.LogScriptEvent($ScriptName,$EventID,2, "Cannot find agent config file at path ($FilePath)")
}
#=======================================================================

# Get Action Account section
#=======================================================================
# Get the action account this script is running under. We will assume that is the default agent action account
try
{
$user = ""
$domain = ""
if($isNano)
{
$user = $env:username
$domain = $env:userdnsdomain
}
else
{
$oNetwork = new-object -comobject "WScript.Network"
$user = $oNetwork.UserName
$domain = $oNetwork.UserDomain
}
If(($user.Length -eq 0) -or ($user -eq "SYSTEM"))
{
$ActionAccount = $user
}
Else
{
$ActionAccount = $domain + "\" + $user
}
}
catch
{
$oAPI.LogScriptEvent($ScriptName, 11, 1, "Failed to retrieve the User name and domain for the action account, error: ", $error.Description)
Exit -1;
}
#=======================================================================

# Get OSVersion section
#=======================================================================
$OSRegKey = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion"
[string]$OSCurrentVersion = (Get-ItemProperty $OSRegKey).CurrentVersion
[string]$OSCurrentBuildNumber = (Get-ItemProperty $OSRegKey).CurrentBuildNumber
[string]$OSCurrentCurrentMajorVersionNumber = (Get-ItemProperty $OSRegKey).CurrentMajorVersionNumber
[string]$OSCurrentCurrentMinorVersionNumber = (Get-ItemProperty $OSRegKey).CurrentMinorVersionNumber

# If Windows 10 or WS2016 use new reg keys else use old keys
IF ($OSCurrentCurrentMajorVersionNumber)
{
[string]$OSVersion = $OSCurrentCurrentMajorVersionNumber + "." + $OSCurrentCurrentMinorVersionNumber + "." + $OSCurrentBuildNumber
}
ELSE
{
[string]$OSVersion = $OSCurrentVersion + "." + $OSCurrentBuildNumber
}
#=======================================================================

# Get Certificate Section
#=======================================================================
$CertRegKey = "HKLM:\SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Machine Settings"
IF(Test-Path $CertRegKey)
{
[array]$CertValue = (Get-ItemProperty $CertRegKey).ChannelCertificateSerialNumber
IF($Certvalue)
{
$CertLoaded = $True
[string]$ThumbPrint = (Get-ItemProperty $CertRegKey).ChannelCertificateHash
$Cert = Get-ChildItem -path cert:\LocalMachine\My | Where-Object {$_.Thumbprint -eq $ThumbPrint}
IF ($Cert)
{
[datetime]$CertExpiresDateTime = $Cert.NotAfter
[string]$CertExpires = $CertExpiresDateTime.ToShortDateString()
$CertIssuerArr = $Cert.Issuer
$CertIssuerSplit = $CertIssuerArr.Split(",")
[string]$CertIssuer = $CertIssuerSplit[0].TrimStart("CN=")
}
ELSE
{
$CertIssuer = "NotFound"
$CertExpires = "NotFound"
}

}
ELSE
{
$CertLoaded = $False
}
}
ELSE
{
$CertLoaded = $False
}
#=======================================================================

# Build IP List from Windows Computer Property
#=======================================================================
#We want to remove Link local IP
[string]$IPList = ""
$IPSplit = $IP.Split(",")
FOREACH ($IPAddr in $IPSplit)
{
[string]$IPAddr = $IPAddr.Trim()
write-host $IPAddr
IF (!($IPAddr.StartsWith("fe80") -or $IPAddr.StartsWith("169.254")))
{
$IPList = $IPList + $IPAddr + ","
}
}
$IPList = $IPList.TrimEnd(",")
#=======================================================================

# Get port connection availability to an array of parents
#=======================================================================
[string]$PortList = ""
IF ($Parents)
{
FOREACH ($Parent in $Parents)
{
[string]$PortAvail = ""
$ip=([System.Net.Dns]::GetHostAddresses($Parent)).IPAddressToString;
$tcp=New-Object net.sockets.tcpclient;$tcp.Connect($Parent,5723);
$out=$tcp.Connected;
# write-host "`nPort 5723 test result for ($Parent) on IP ($ip) : ($out)"

IF ($out)
{
$PortAvail = "Open"
}
ELSE
{
$PortAvail = "Blocked"
}

$ParentSplit = $Parent.Split(".")
[string]$ServerName = $ParentSplit[0]
$PortList = $PortList + $ServerName + ": " + $PortAvail + ", "
}
$PortList = $Portlist.TrimEnd(", ")
}
#=======================================================================


# Discovery Script section - Discovery scripts get this
#=================================================================================
$instance = $DiscoveryData.CreateClassInstance("$MPElement[Name='SCOM.Management.Agent.Class']$")
$instance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $Computername)
$instance.AddProperty("$MPElement[Name='SCOM.Management.Agent.Class']/AgentVersion$", $SCOMAgentVersion)
$instance.AddProperty("$MPElement[Name='SCOM.Management.Agent.Class']/UpdateRollup$", $SCOMAgentURVersion)
$instance.AddProperty("$MPElement[Name='SCOM.Management.Agent.Class']/ADIntEnabled$", $ADIntEnabled)
$instance.AddProperty("$MPElement[Name='SCOM.Management.Agent.Class']/ManagementGroups$", $MGList)
$instance.AddProperty("$MPElement[Name='SCOM.Management.Agent.Class']/OMSWorkspaces$", $OMSList)
$instance.AddProperty("$MPElement[Name='SCOM.Management.Agent.Class']/ProxyURL$", $ProxyURL)
$instance.AddProperty("$MPElement[Name='SCOM.Management.Agent.Class']/PSVersion$", $PSVersion)
$instance.AddProperty("$MPElement[Name='SCOM.Management.Agent.Class']/CLRVersion$", $CLRVersion)
$instance.AddProperty("$MPElement[Name='SCOM.Management.Agent.Class']/PrimaryMS$", $PrimaryMS)
$instance.AddProperty("$MPElement[Name='SCOM.Management.Agent.Class']/FailoverList$", $FailoverList)
$instance.AddProperty("$MPElement[Name='SCOM.Management.Agent.Class']/ActionAccount$", $ActionAccount)
$instance.AddProperty("$MPElement[Name='SCOM.Management.Agent.Class']/OSVersion$", $OSVersion)
$instance.AddProperty("$MPElement[Name='SCOM.Management.Agent.Class']/InstallPath$", $SCOMAgentPath)
$instance.AddProperty("$MPElement[Name='SCOM.Management.Agent.Class']/CertLoaded$", $CertLoaded)
$instance.AddProperty("$MPElement[Name='SCOM.Management.Agent.Class']/CertExpires$", $CertExpires)
$instance.AddProperty("$MPElement[Name='SCOM.Management.Agent.Class']/ThumbPrint$", $ThumbPrint)
$instance.AddProperty("$MPElement[Name='SCOM.Management.Agent.Class']/CertIssuer$", $CertIssuer)
$instance.AddProperty("$MPElement[Name='SCOM.Management.Agent.Class']/IP$", $IPList)
$instance.AddProperty("$MPElement[Name='SCOM.Management.Agent.Class']/Connection$", $PortList)
$DiscoveryData.AddInstance($instance)

# Return Discovery Items Normally
$DiscoveryData
# Return Discovery Bag to the command line for testing (does not work from ISE)
# $momapi.Return($DiscoveryData)
#=================================================================================


# 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,"`nScript has completed. `nAgent Version: ($SCOMAgentVersion). `nAgent Rollup: ($SCOMAgentURVersion). `nADIntEnabled: ($ADIntEnabled). `nManagement Group list: ($MGList). `Log Analytics Workspace list: ($OMSList). `nProxyURL: ($ProxyURL). `nPowerShell Version: ($PSVersion). `nCLR Version: ($CLRVersion). `n Primary MS: ($PrimaryMS). `nSecondary MS Failover list: ($FailoverList). `nAction Account: ($ActionAccount). `nOS Version: ($OSVersion). `nSCOM Agent Path: ($SCOMAgentPath). `nCertLoaded: ($CertLoaded). `nCert Expiration: ($CertExpires). `nCert Thumbprint: ($ThumbPrint). `nCert Issuer: ($CertIssuer). `nIP ($IPList). `nConnection: ($PortList). `nScript runtime: ($ScriptTime) seconds.")
#=================================================================================
# End of script
</Script></ScriptBody>
<Parameters>
<Parameter>
<Name>SourceId</Name>
<Value>$MPElement$</Value>
</Parameter>
<Parameter>
<Name>ManagedEntityId</Name>
<Value>$Target/Id$</Value>
</Parameter>
<Parameter>
<Name>ComputerName</Name>
<Value>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Value>
</Parameter>
<Parameter>
<Name>MGName</Name>
<Value>$Target/ManagementGroup/Name$</Value>
</Parameter>
<Parameter>
<Name>IP</Name>
<Value>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/IPAddress$</Value>
</Parameter>
</Parameters>
<TimeoutSeconds>600</TimeoutSeconds>
</DataSource>
</Discovery>