By default the assemblies necessary to complete the discovery and monitoring are installed under the \%ProgramData\% directory. You can set this to any valid path to install them in a different location.
IntervalSeconds
int
$Config/IntervalSeconds$
Interval Seconds
The interval that this Discovery is run
ScriptTraceEnabled
int
$Config/ScriptDebugEnabled$
Script Trace Enabled
To enable detailed logging of this Discovery set this to 1, setting it to 0 will disable logging. The logs are sent to the Windows Event Log and can be found with the other Operations Manager logs.
UseSsl
int
$Config/UseSsl$
Use SSL
If SSL must be used to communicate with TFS set this to 1, if not set it 0. This override is only applicable to Application Tier and Proxy Servers.
Port
int
$Config/Port$
Port
The Port that is used to communicate with this component of TFS. This override is only applicable to Application Tier and Proxy Servers.
Source Code:
<DataSourceModuleType ID="TeamFoundationServer2017.TfsPowerShellDiscoveryDataSource" Accessibility="Public" RunAs="TeamFoundationServer2017.Tfs2017UserProfile" Batching="false">
<Configuration>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="Component" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="ClassName" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="BaseInstallPath" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="IntervalSeconds" type="xsd:integer"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="ScriptDebugEnabled" type="xsd:integer"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="UseSsl" type="xsd:integer"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="Port" type="xsd:integer"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="BaseInstallPath" Selector="$Config/BaseInstallPath$" ParameterType="string"/>
<OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="int"/>
<OverrideableParameter ID="ScriptTraceEnabled" Selector="$Config/ScriptDebugEnabled$" ParameterType="int"/>
<OverrideableParameter ID="UseSsl" Selector="$Config/UseSsl$" ParameterType="int"/>
<OverrideableParameter ID="Port" Selector="$Config/Port$" ParameterType="int"/>
</OverrideableParameters>
<ModuleImplementation Isolation="OwnProcess">
<Composite>
<MemberModules>
<DataSource ID="TfsPowerShellDiscoveryProvider" TypeID="Windows!Microsoft.Windows.TimedPowerShell.DiscoveryProvider">
<IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
<SyncTime/>
<ScriptName>TfsDiscovery.ps1</ScriptName>
<ScriptBody><Script>param($sourceId, $managedEntityId, $component, $baseInstallPath, $className, $port, $useSsl, $scriptDebugEnabled)
###
# This discovery will check if a specific Tfs component is installed, query it's topography via a C# Class
# To insure errors don't go on noticed $ErrorActionPreference will be set to Stop.
###
# $sourceId/$managedEntityId - GUID used to identify this discovery, simply passed through to the SCOM Script API
# Discovery Object
# $component - Tfs Component ("ApplicationTier", "VersionControlProxy") to look for
# $baseInstallPath - An override location to install the binary - if not provided a default will be used, see Compute-InstallPath
# $className - The name of the class (from with in ManagementPack namespace/assembly) that should be used for this discovery
# $port - The port used for the Tfs Instance (default to 8080 for ATs and 8081 for Proxies, and ignored for everything else)
# $useSsl - A flag to control how we should communicate with tfs, when true we use https, when false (the default) we use http
# $scriptDebugEnabled - A flag to control if debug information should be logged
# Errors and Warnings are always logged
#
# Verifies that the binary files has been placed in the provided install directory
# It can fail if we can't a lock using the mutex for the install path
function Validate-Install
{
param ([string] $installPath)
## Need void here to prevent powershell from adding a space to the caller outout
[void] [System.Threading.Mutex]$mutex
[bool] $gotMutex = $false
try
{
[string] $mutextName = ("Global\{0}" -f $installPath.Replace("\",";"))
Log-Message -message ("Creating Mutex: {0}" -f $mutextName) -severity $Script:severityInfo
[bool]$wasCreated = $false
$mutex = New-Object System.Threading.Mutex($true, $mutextName, [ref] $wasCreated)
if ($wasCreated)
{
Log-Message -message "Created Mutex" -severity $Script:severityInfo
$gotMutex = $true
}
else
{
Log-Message -message "Waiting for up to 3 secs for Mutext" -severity $Script:severityInfo
try
{
$gotMutex = $mutex.WaitOne(3000)
}
catch [System.Threading.AbandonedMutexException]
{
## We have no problem just taking over an Abandoned Mutex
Log-Message -message "Mutex was Previously Abandoned" -severity $Script:severityInfo
#
# Does the work of Verifying that the binaries files have been placed.
# Assumes the caller already obtained the needed Mutext to prevent raise conditions
function Validate-Install-UnderMutex
{
param ([string] $installPath)
#
# Adds information about the current user to the log
function Log-User
{
$owner = (Get-WmiObject win32_process | Where-Object {$_.ProcessId -eq $pid }).getowner()
#
# Calls ManagementPack.exe and logs the response. Additionally parse out the log and returns the pay load
# $forDiscovery should be $true when running a Discovery and $false for monitors
function Run-ManagementPack
{
param ([string] $baseInstallPath, [bool] $forDiscovery, [string] $className, [string] $params)
[int] $severity = $Script:severityInfo
[string] $message = "Exit Code $exitCode from Calling $command $([System.Environment]::NewLine)$response"
# $exitCode = 0 - No errors, log severity info
# $exitCode = 1 - At least one error and we were able get some data, log severity Error
# $exitCode = 2 - Failed to get data, throw
# $exitCode = Anything Else - Unexpected error, throw
if (($exitCode -eq 0) -or ($exitCode -eq 1))
{
if ($status -gt 0)
{
$severity = $Script:severityError
}
Log-Message -message $message -severity $severity
}
else
{
throw [Exception] $message
}
# At this point response should hold a log and a payload, return the payload
[string] $logBarrior = "**[[<<END OF LOG>>]]**"
[int] $index = $response.IndexOf($logBarrior)
if ($index -lt 0)
{
throw [Exception] "Failed to find $logBarrior in response: $response"
}
#
# Takes a string that could be very long and breaks it into smaller chunks
function Get-Chunks
{
param ([string] $message)
$chunkSize = 20480 #20K
$result = @{}
#
# Wrapper to obtain and cache the value to MOM COM Script API
function Get-MomScriptApi
{
if ($Script:MomSciptApi -eq $null)
{
$Script:MomSciptApi = new-object -comObject 'MOM.ScriptAPI'
}
return $Script:MomSciptApi
}
#
# Start of Specific Functions
########################################################################################
#
# Returns the SCOM Script API Discovery Data object populated with what ever data we can find.
# It return null if the component is not configured
function Get-DiscoveryData
{
param ([string] $sourceId, [string] $managedEntityId, [string] $component, [string] $baseInstallPath, [string] $className, [int] $port, [bool] $useSsl)
if (-not([String]::IsNullOrEmpty($component)))
{
#
# $component will be set to null for things like VsoAgent, which Don't have an "IsConfigured" node in the registry
if (-not(Get-IsConfigured $component))
{
#
# This it is not Configured there nothing for us to do, but the initial discovery provider should have found that already
Log-Message -message ("Component Not Configured on this machine: {0}" -f $component) -severity $Script:severityWarn
return $null
}
}
#
# Given the XML returned by the C# Class, this will Create the SCOM Script API Discovery Data object and fill it in.
# The XML is validated, violations result in an exception being thrown
function Unpack-DiscoveryXml
{
param ([string] $xmlContent, [string] $sourceId, [string] $managedEntityId)
#
# This will query the component using the C# exe and return a string containing XML that describes the objects
# and relationships found.
# If a fatal error is found an exception is thrown.
function Get-DiscoveryXml
{
param ([string] $baseInstallPath, [string] $className, [int] $port, [bool] $useSsl)