| Again just a very fast publishing of my PowerShell discovery template for SCOM (System Center Operations Manager, OpsMgr) 2007 and newer. The script can be run from PowerShell command window (for which it generates the target instance ID and the target class ID randomly). It automatically detects if it is running customized from HealthService or from the command line in debug mode and contains debug/error output functionality which can either write into the Operations Manager event log or just to the console if you use the -dbg switch.
The script is explicitly developed to support even PowerShell 2.0 which is a common requirements with my customers.
I usually discover two additional properties for every object - the LastRunTime and ScriptError - which are easy for operational stability monitoring.
Any additional questions, send me an email.
param(
[string] $targetClassId = [Guid]::NewGuid().ToString('b'), # Note: replace with $MPElement$
[string] $targetInstId = [Guid]::NewGuid().ToString('b'), # Note: replace with $Target/Id$
[string] $computerName = ('{0}.{1}' -f (gwmi Win32_ComputerSystem).DnsHostName, (gwmi Win32_ComputerSystem).Domain)
)
$errorActionPreference = 'Stop'
# Note: if the caller does not supply the $targetClassId we assume
# it must be run from command line in a debug session. Note
# that the parameter name is case-sensitive
# Note: PowerShell 2.0 does not have .Contains() method on [string[]] type
[bool] $fromCmd = -not ([Collections.ArrayList] $PSBoundParameters.Keys).Contains('targetClassId')
[__ComObject] $scom = New-Object -Com MOM.ScriptAPI
[__ComObject] $discoData = $scom.CreateDiscoveryData(0, $targetClassId, $targetInstId)
[bool] $ok = (-not [object]::Equals($scom, $null)) -and (-not [object]::Equals($discoData, $null))
if (-not $ok) { throw 'SEVECEK: An error occured during the very script initialization' }
function MSG (
[string] $message,
[ValidateRange(10001,19999)] [int] $id = 10001,
[ValidateSet('info', 'warn', 'err')] [string] $type = 'info',
[switch] $dbg
)
{
[int] $evType = 0
# Note: cannot use host's colors here because the script is not running
# with a console and the colors are $null in HealthService
[string] $color = 'Yellow'
switch ($type) {
'info' { $evType = 0 ; $color = 'Yellow' }
'warn' { $evType = 1 ; $color = 'Magenta' }
'err' { $evType = 2 ; $color = 'Red' }
}
if (-not $dbg) { $scom.LogScriptEvent('SEVECEK Script', $id, $evType, $message) }
if ($fromCmd) { Write-Host ('{0,5}: {1,4}: {2}' -f $id, $type, $message) -Fore $color }
}
# Note: would not display if we are not running from cmd
MSG -dbg 'Running from cmd'
#
#
#
[Collections.ArrayList] $foundInstances = @()
try {
for ($i = 1; $i -le 2; $i++) {
[PSCustomObject] $newInstance = New-Object PSCustomObject
Add-Member -Input $newInstance -MemberType NoteProperty -Name display -Value 'Sevecek test object 1'
[void] $foundInstances.Add($newInstance)
}
} catch {
$exp = $_.Exception
[string] $expMsg = ''
[string[]] $errorCodes = @()
do {
$expMsg = "{0}`r`n{1}" -f $expMsg, $exp.Message
function ConvertTo-StringError($value)
{
[string] $strValue = ''
if (-not ([object]::Equals($value, $null))) {
$strValue = '{0}' -f $value
[string] $hexElement = ''
try { $hexElement = '0x{0:X8}' -f $value } catch { }
if ($hexElement -ne '') { $strValue = '{0} ({1})' -f $strValue, $hexElement }
}
return $strValue.Trim()
}
$errorCodes += ConvertTo-StringError $exp.HResult
$errorCodes += ConvertTo-StringError $exp.ErrorCode
$errorCodes += ConvertTo-StringError $exp.ErrorCode.value__
$exp = $exp.InnerException
} while (-not ([object]::Equals($exp, $null)))
MSG ("SEVECEK: An error occured during script execution: {0}`r`nError codes: {1}" -f $expMsg, (($errorCodes | ? { $_ -ne '' }) -join ' | ')) 19999 err
$ok = $false
}
foreach ($oneFoundInstance in $foundInstances) {
[__ComObject] $newInst = $discoData.CreateClassInstance('$MPElement[Name="Sevecek.Monitoring.SensitiveUser"]$')
$newInst.AddProperty('$MPElement[Name="Windows!Microsoft.Windows.Computer"]/PrincipalName$', $computerName)
$newInst.AddProperty('$MPElement[Name="System!System.Entity"]/DisplayName$', $oneFoundInstance.display)
$newInst.AddProperty('$MPElement[Name="Sevecek.Monitoring.Base"]/LastRunTime$', [DateTime]::Now)
$newInst.AddProperty('$MPElement[Name="Sevecek.Monitoring.Base"]/ScriptError$', (-not $ok))
$discoData.AddInstance($newInst)
}
#
#
#
if ($fromCmd) {
# Note: when running debug from command line we return the XML
# to take a look. The .Return() method does not have a return
# value, it writes the output XML into console (not stdout) directly
$scom.Return($discoData)
Write-Host; MSG -dbg 'Finished.'
} else {
# Note: when running from a module data source we return
# the pure object to be handled completelly by the caller
return $discoData
}
|