Learn how your company can work directly with me or one of my peers.
The benefit is not just having an experienced engineer helping you manage the health of your environment. Through Premier Field Engineering, your company will have access to a wealth of knowledge from all of PFE and a channel into the product group to answer the most complex questions.
This is a continuation of a previous post. The only difference is this accepts a literal expression, rather than a group system name.
As with the other script example, there is no reverse action. If you specify a group that contains hundreds of windows computer objects and it was a mistake, you'll have to manually delete hundreds of health service instances from your secure distribution in the Run As Account.
The script accepts the below parameters – all are required. First set of variables (with a “$”) can be uncommented if executing without parameters, and the second set (with a “-“) is an example of parameter format you would specify if running with parameter names.
# $RootManagementServer = "srvrms01" # $DatabaseServer = "srvsql01" # $DatabaseName = "OperationsManager" # $Expression = "FQDN like '%hyper%'" # $Account = "Test Run As Account" # $BinariesFolder = "C:\Program Files\System Center Operations Manager 2007\SDK Binaries" # -RootManagementServer srvrms01 # -DatabaseServer srvsql01 # -DatabaseName OperationsManager # -Expression "FQDN like '%hyper%'" # -Account "Test Run As Account" # -BinariesFolder "f:\Program Files\System Center Operations Manager 2007\SDK Binaries" # -Debug true
param($RootManagementServer, $DatabaseServer, $DatabaseName, $Expression, $Account, $BinariesFolder, $DebugFlag) #Local
#-------------------------------------------------------------------------------------Start Main
# This function controls program flow.
function Main
{
$CollectionHSIDs = CreateCollectionHSIDs
ValidateSnapIn
$MG = ConnectToManagementGroup
$CollectionHSOs = CreateCollectionHSOs
$NumInstances = $CollectionHSOs.Count
LoadHelperClass
AddHealthServiceToAccountDistributionList
Remove-ManagementGroupConnection $RootManagementServer
QuitScript $QuitSuccess "Workflow completed successfully."
}#------------------------------------------------------------------------------------End Main
#-------------------------------------------------------------------------------------Start AddHealthServiceToAccountDistributionList
# This function adds health service instances to the Run As Account distribution list.
function AddHealthServiceToAccountDistributionList
# Add health service objects to Run As Account distribution list.
$data = $MG.ManagementGroup.GetMonitoringSecureData() | Where-Object {$_.Name -eq $Account}
[Helper]::ApproveCredentialForDistribution($MG.ManagementGroup, $data, $CollectionHSOs)
if ($DebugFlag) {DebugEvent "Sequence 6 - Completed function AddHealthServiceToAccountDistributionList"}
}#------------------------------------------------------------------------------------End AddHealthServiceToAccountDistributionList
#-------------------------------------------------------------------------------------Start CreateCollectionHSIDs
# This function queries the operational database for members of the specified windows
# computer group and resolves the health service id of those instances. Then adds
# those health service id's to a collection.
# The use of system.data.sqlclient.sqlconnection requires Windows Server 2003 SP2+,
# Windows Server 2008 or Windows Server 2008 R2 (except core editions).
function CreateCollectionHSIDs
# Setup the SQL connection
$connection = new-object system.data.sqlclient.sqlconnection("Data Source=$DatabaseServer;Initial Catalog=$DatabaseName;Integrated Security=SSPI;");
# Define TSQL
[string]$query =
"
/*
Get Health Service IDs
Based on literal expression
*/
SELECT distinct ME.Id AS 'HSID'
from ManagedEntityGenericView AS ME INNER JOIN
ManagedTypeView AS MT ON ME.MonitoringClassId = MT.Id INNER JOIN
RelationshipGenericView AS REL ON ME.DisplayName = REL.TargetMonitoringObjectDisplayName
where MT.Name = 'Microsoft.SystemCenter.HealthService' AND
ME.IsDeleted <> 1 AND
($Expression)
# Create the dataset
$execute = new-object system.data.sqlclient.sqldataadapter ($query, $connection)
$dataset = new-object system.data.dataset
$execute.Fill($dataset) | Out-Null #speeds processing
# Create an empty collection
[System.Collections.ArrayList]$CollectionHSIDs = @()
# Add each row in dataset to the collection
foreach ($row in $dataset.Tables[0])
$CollectionHSIDs.Add($row) | Out-Null #speeds processing
}
if ($DebugFlag) {DebugEvent "Sequence 1 - Completed function CreateCollectionHSIDs"}
# Pass collection to main script.
return $CollectionHSIDs
}#------------------------------------------------------------------------------------End CreateCollectionHSIDs
#-------------------------------------------------------------------------------------Start CreateCollectionHSOs
# This function adds health service objects to a collection.
function CreateCollectionHSOs
# Create an empty collection.
[System.Collections.ArrayList]$CollectionHSOs = @()
# Add each Health Service instance to the collection.
foreach ($HSID in $CollectionHSIDs)
$CollectionHSOs.Add((Get-MonitoringObject -Id $HSID.HSID.ToString())) | Out-Null #speeds processing
if ($DebugFlag) {DebugEvent "Sequence 4 - Completed function CreateCollectionHSOs"}
return $CollectionHSOs
}#------------------------------------------------------------------------------------End CreateCollectionHSOs
#-------------------------------------------------------------------------------------Start LoadHelperClass
# This function is used to test and load the helper class that enables distribution.
function LoadHelperClass
# Create variable to test whether type is already added.
$b=$false
$b = Get-Type ([helper])
trap [exception] {continue} #always throws exception if class isn't added.
# Add Type Definition for helper class if not already added
if (!$b)
Add-Type –typedefinition $src -ReferencedAssemblies ($BinariesFolder + "\Microsoft.EnterpriseManagement.OperationsManager.dll"), 'System.Xml'
QuitScript $QuitFailure "Error in function LoadHelperClass: Unable to load helper class."
if ($DebugFlag) {DebugEvent "Sequence 5 - Completed function LoadHelperClass"}
# Recycle variable
Remove-Variable b
}#------------------------------------------------------------------------------------End LoadHelperClass
#-------------------------------------------------------------------------------------Start AddAccountToProfile
# This function associates Run As Account to Run As Profile.
function AddAccountToProfile
# This function not being used at this time.
}#------------------------------------------------------------------------------------End AddAccountToProfile
#-------------------------------------------------------------------------------------Start ValidateSnapIn
# This function is used to test and load the OM snapin.
function ValidateSnapIn
# Create a variable to hold OM snapin
$b = Get-PSSnapin | Where-Object {$_.Name -like "*Microsoft.EnterpriseManagement.OperationsManager.Client*"}
# Test variable. If empty, add OM snapin.
Add-PSSnapin -Name "Microsoft.EnterpriseManagement.OperationsManager.Client"
# Refresh variable after snapin load attempt.
# If snapin failed to load, quit script - cannot move forward.
QuitScript $QuitFailure "Error in function ValidateSnapIn: Unable to load OM snapin."
if ($DebugFlag) {DebugEvent "Sequence 2 - Completed function ValidateSnapin"}
Remove-Variable -Name b
}#------------------------------------------------------------------------------------End ValidateSnapIn
#-------------------------------------------------------------------------------------Start ConnectToManagementGroup
# This function is used to connect to the root management server and set location.
function ConnectToManagementGroup
# Create variable to hold connection.
$b = (Get-ManagementGroupConnection).ManagementServerName
# Test variable. If empty, attempt to create the connection.
if ($b -ne $RootManagementServer)
$NewConnection = New-ManagementGroupConnection -ConnectionString:$RootManagementServer
# Refresh variable after connection attempt.
# If still unable to connect, quit script - cannot move forward.
QuitScript $QuitFailure "Error in function ConnectToManagementGroup: Unable to establish connection to $RootManagementServer."
# Now that we have a connection, set location to OM monitoring drive.
Set-Location "OperationsManagerMonitoring::"
else
# Perhaps connection already existed, so we'll just move on.
$NewConnection = Get-ManagementGroupConnection
if ($DebugFlag) {DebugEvent "Sequence 3 - Completed function ConnectToManagementGroup"}
return $NewConnection
}#------------------------------------------------------------------------------------End ConnectToManagementGroup
#-------------------------------------------------------------------------------------Start QuitScript
# This function is used to set error levels and return details.
function QuitScript ($Level, $Detail)
if ($Level -eq 1)
$Message = "$Detail Account distribution failed for $Account."
Write-EventLog -LogName Application -Source OM-SecureDist -EventID 100 -EntryType Error -Message $Message
exit
$Message = "$Detail Distribution occurred for $Account for $NumInstances health service instance(s)."
Write-EventLog -LogName Application -Source OM-SecureDist -EventID 100 -EntryType Information -Message $Message
}#------------------------------------------------------------------------------------End QuitScript
#-------------------------------------------------------------------------------------Start DebugEvent
# This function is used to write debug events.
function DebugEvent ($Detail)
$Message = "$Account : $Detail"
Write-EventLog -LogName Application -Source OM-SecureDist -EventID 101 -EntryType Information -Message $Message
}#------------------------------------------------------------------------------------End DebugEvent
#-------------------------------------------------------------------------------------Start Get-Type
# This function is used to test whether the helper class has been added.
# Successfully detects when type is added, but throws exception when it's not.
# http://solutionizing.net/2009/01/01/powershell-get-type-simplified-generics/
function global:Get-Type ($type = $(Throw "Please specify a type"))
trap [System.Management.Automation.RuntimeException] { Throw ($_.Exception.Message) }
if ($Args -and $Args.Count -gt 0)
$types = $Args[0] -as [type[]]
if (-not $types)
$types = [type[]] $Args
if ($genericType = [type] ($type + '`' + $types.Count))
$genericType.MakeGenericType($types)
[type] $type
}#------------------------------------------------------------------------------------End Get-Type
#-------------------------------------------------------------------------------------Start variables
# Set variables
$QuitFailure = 1
$QuitSuccess = 0
# Source for helper class
$src = @"
using Microsoft.EnterpriseManagement;
using Microsoft.EnterpriseManagement.Monitoring;
using System.Collections.Generic;
public class Helper {
public static void ApproveCredentialForDistribution(ManagementGroup mg, ISecuredData credential, MonitoringObject[] targets) {
mg.ApproveCredentialForDistribution<MonitoringObject>(credential, new List<MonitoringObject>(targets));
"@
# Set Debug Flag
if ($DebugFlag -and $DebugFlag -ne "true")
Remove-Variable DebugFlag
# Fix Expression Filter
$Expression = $Expression.Replace("FQDN", "ME.DisplayName")
#-------------------------------------------------------------------------------------End variables
#-------------------------------------------------------------------------------------Start EventLogSourceCheck
# Check if the OM-SecureDist source has been added to the Operations Manager log.
$b=[system.diagnostics.eventlog]::SourceExists("OM-SecureDist")
trap [Exception] {continue}
# Create the source if it doesn't exist.
# Requires elevated privileges.
New-EventLog -Source OM-SecureDist -LogName Application
#-------------------------------------------------------------------------------------End EventLogSourceCheck
#-------------------------------------------------------------------------------------Start variables for local runtime
# $RootManagementServer = "srvrms01"
# $DatabaseServer = "srvsql01"
# $DatabaseName = "OperationsManager"
# $Expression = "FQDN like '%hyper%'"
# $Expression = $Expression.Replace("FQDN", "ME.DisplayName")
# $Account = "Test Run As Account"
# $BinariesFolder = "C:\Program Files\System Center Operations Manager 2007\SDK Binaries"
# -RootManagementServer srvrms01
# -DatabaseServer srvsql01
# -DatabaseName OperationsManager
# -Group Microsoft.SystemCenter.AllComputersGroup
# -Account "Test Run As Account"
# -BinariesFolder "f:\Program Files\System Center Operations Manager 2007\SDK Binaries"
# -Debug true
#-------------------------------------------------------------------------------------End variables for local runtime
#-------------------------------------------------------------------------------------Start main program
Main
Always test scripts you find on the internet before implementing in production.
Also see the other one if you want to use group criteria.
Awesome article. Miss you as my DSE brotha. Hope all is well! God Speed!