Private.ps1
####################################################################### # PRIVATE ####################################################################### <# It is assumed that a management group connection object exists already: $MG #> Function Add-MPReference { Param ( $UnsealedMPName, $ReferenceMPName, $ReferenceAlias ) #Get the Reference MP Write-Verbose "Getting Reference MP $ReferenceMPName`..." $strMPquery = "Name = '$ReferenceMPName' AND Sealed = 'TRUE'" $mpCriteria = New-Object Microsoft.EnterpriseManagement.Configuration.ManagementPackCriteria($strMPquery) $RefMP = $MG.GetManagementPacks($mpCriteria)[0] If (!$RefMP) { Write-Error "Unable to find the Reference Sealed MP with the name '$ReferenceMPName'." Return $false } else { $Version = $RefMP.Version $KeyToken = $RefMP.KeyToken Write-Verbose "Reference MP Version: $Version" Write-Verbose "Reference MP Key Token: $KeyToken" } #Get the destination unsealed MP Write-Verbose "Getting Unsealed MP $UnsealedMPName`..." $strMPquery = "Name = '$UnsealedMPName' AND Sealed = 'FALSE'" $mpCriteria = New-Object Microsoft.EnterpriseManagement.Configuration.ManagementPackCriteria($strMPquery) $DestMP = $MG.GetManagementPacks($mpCriteria)[0] If (!$DestMP) { Write-Error "Unable to find the unsealed MP with the name '$UnsealedMPName'." Return $false } else { Write-Verbose "Adding reference for $ReferenceMPName`..." $objMPRef = New-Object Microsoft.EnterpriseManagement.Configuration.ManagementPackReference($DestMP, $ReferenceMPName, $KeyToken, $Version) #Verify and save the monitor Write-Verbose "Verifying $UnsealedMPName and save changes..." Try { $DestMP.References.Add($ReferenceAlias, $objMPRef) $DestMP.verify() $DestMP.AcceptChanges() $Result = $true Write-Verbose "MP Reference for sealed MP '$ReferenceMPName' (Alias: $ReferenceAlias; KeyToken: $KeyToken; Version: $Version) added to '$UnsealedMPName'." } Catch { $Result = $false $DestMP.RejectChanges() Write-Error "Unable to add MP Reference for $ReferenceMPName (Alias: $ReferenceAlias; KeyToken: $KeyToken; Version: $Version) to $UnsealedMPName." } } $Result } ####################################################################### Function Connect-OMManagementGroup { <# .Notes Author: Tao Yang ( https://blog.tyang.org/ , https://blog.tyang.org/2018/04/18/opsmgrextended-powershell-module-is-now-on-github-and-psgallery/ ) .Synopsis Connect to OpsMgr Management Group using SDK .Description Connect to OpsMgr Management Group Data Access Service using SDK .Parameter -SDKConnection OpsMgr SDK Connection object (SMA connection or hash table). .Parameter -SDK Management Server name. .Parameter -UserName Alternative user name to connect to the management group (optional). .Parameter -Password Alternative password to connect to the management group (optional). .Parameter -DLLPath Optionally, specify an alternative path to the OpsMgr SDK DLLs if they have not been installed in GAC. .Example # Connect to OpsMgr management group via management server "OpsMgrMS01" Connect-OMManagementGroup -SDK "OpsMgrMS01" .Example # Connect to OpsMgr management group via management server "OpsMgrMS01" using different credential $Password = ConvertTo-SecureString -AsPlainText "password1234" -force $MG = Connect-OMManagementGroup -SDK "OpsMgrMS01" -Username "domain\SCOM.Admin" -Password $Password .Example # Connect to OpsMgr management group via management server "OpsMgrMS01" using current user's credential $MG = Connect-OMManagementGroup -SDK "OpsMgrMS01" OR $MG = Connect-OMManagementGroup -Server "OPSMGRMS01" .Example # Connect to OpsMgr management group using the SMA connection "OpsMgrSDK_TYANG" $SDKCOnnection = Get-AutomationConnection "OpsMgrSDK_TYANG" $MG = Connect-OMManagementGroup -SDKConnection $SDKConnection #> [CmdletBinding()] PARAM ( [Parameter(ParameterSetName='SMAConnection',Mandatory=$true,HelpMessage='Please specify the SMA Connection object')][Alias('Connection','c')][Object]$SDKConnection, [Parameter(ParameterSetName='IndividualParameter',Mandatory=$true,HelpMessage='Please enter the Management Server name')][Alias('DAS','Server','s')][String]$SDK, [Parameter(ParameterSetName='IndividualParameter',Mandatory=$false,HelpMessage='Please enter the user name to connect to the OpsMgr management group')][Alias('u')][String]$Username = $null, [Parameter(ParameterSetName='IndividualParameter',Mandatory=$false,HelpMessage='Please enter the password to connect to the OpsMgr management group')][Alias('p')][SecureString]$Password = $null ) If ($SDKConnection) { $SDK = $SDKConnection.ComputerName $Username = $SDKConnection.Username $Password = ConvertTo-SecureString -AsPlainText $SDKConnection.Password -force } #Check User name and password parameter If ($Username) { If (!$Password) { Write-Error "Password for user name $Username must be specified!" Return $null } } #Connect to the management group $MGConnSetting = New-Object Microsoft.EnterpriseManagement.ManagementGroupConnectionSettings($SDK) If ($Username -and $Password) { $MGConnSetting.UserName = $Username $MGConnSetting.Password = $Password } $MG = New-Object Microsoft.EnterpriseManagement.ManagementGroup($MGConnSetting) $MG } ####################################################################### Function New-OMManagementPack { <# .Notes Author: Tao Yang ( https://blog.tyang.org/ , https://blog.tyang.org/2018/04/18/opsmgrextended-powershell-module-is-now-on-github-and-psgallery/ ) .Synopsis Create a new unsealed management pack in an OpsMgr management group. .Description Create a new unsealed management pack in an OpsMgr management group using OpsMgr SDK. A boolean value $true will be returned if the MP creation has been successful, otherwise, a boolean value of $false is returned if any there are any errors occurred during the creation process. .Parameter -SDKConnection OpsMgr SDK Connection object (SMA connection or hash table). .Parameter -SDK Management Server name .Parameter -UserName Alternative user name to connect to the management group (optional). .Parameter -Password Alternative password to connect to the management group (optional). .Parameter -Name Management Pack name .Parameter -DisplayName Management Pack display name .Parameter -Description Management Pack description .Parameter -Version Management Pack version .Example # Connect to OpsMgr management group via management server "OpsMgrMS01" and then create an unsealed management pack with the following properties: Management Server: "OpsMgrMS01" Username: "domain\SCOM.Admin" Password "password1234" Name: "TYANG.Lab.Test" DisplayName: "TYANG Lab Test" Version: 1.0.0.0 (default version number) $Password = ConvertTo-SecureString -AsPlainText "password1234" -force $MPCreated = New-OMManagementPack -SDK "OpsMgrMS01" -Username "domain\SCOM.Admin" -Password $Password -Name "TYANG.Lab.Test" -DisplayName "TYANG Lab Test" .Example # Connect to OpsMgr management group via management server "OpsMgrMS01" and then create an unsealed management pack with the following properties: OpsMgrSDK Connection (Used in SMA): "OpsMgrSDK_TYANG" Name: "TYANG.Lab.Test" DisplayName: "TYANG Lab Test" Description "Test Managemnet Pack Description" Version: 0.0.0.1 $SDKConnection = Get-AutomationConnection -Name OpsMgrSDK_TYANG $MPCreated = New-OMManagementPack -SDKConnection $SDKConnection -Name "TYANG.Lab.Test" -DisplayName "TYANG Lab Test" -Description "Test Managemnet Pack Description" -Version "0.0.0.1" #> [CmdletBinding()] PARAM ( [Parameter(ParameterSetName='SMAConnection',Mandatory=$true,HelpMessage='Please specify the SMA Connection object')][Alias('Connection','c')][Object]$SDKConnection, [Parameter(ParameterSetName='IndividualParameter',Mandatory=$true,HelpMessage='Please enter the Management Server name')][Alias('DAS','Server','s')][String]$SDK, [Parameter(ParameterSetName='IndividualParameter',Mandatory=$false,HelpMessage='Please enter the user name to connect to the OpsMgr management group')][Alias('u')][String]$Username = $null, [Parameter(ParameterSetName='IndividualParameter',Mandatory=$false,HelpMessage='Please enter the password to connect to the OpsMgr management group')][Alias('p')][SecureString]$Password = $null, [Parameter(Mandatory=$true,HelpMessage='Please enter management pack name')][String]$Name, [Parameter(Mandatory=$true,HelpMessage='Please enter management pack display name')][String]$DisplayName, [Parameter(Mandatory=$false,HelpMessage='Please enter management pack description')][String]$Description, [Parameter(Mandatory=$false,HelpMessage='Please enter management pack version')][System.Version]$Version="1.0.0.0" ) #Connect to MG If ($SDKConnection) { Write-Verbose "Connecting to Management Group via SDK $($SDKConnection.ComputerName)`..." $MG = Connect-OMManagementGroup -SDKConnection $SDKConnection $SDK = $SDKConnection.ComputerName $Username = $SDKConnection.Username $Password= ConvertTo-SecureString -AsPlainText $SDKConnection.Password -force } else { Write-Verbose "Connecting to Management Group via SDK $SDK`..." If ($Username -and $Password) { $MG = Connect-OMManagementGroup -SDK $SDK -UserName $Username -Password $Password } else { $MG = Connect-OMManagementGroup -SDK $SDK } } $mpStore = New-Object Microsoft.EnterpriseManagement.Configuration.IO.ManagementPackFileStore $mp = New-Object Microsoft.EnterpriseManagement.Configuration.ManagementPack($Name, $DisplayName, $version, $mpStore) $mp.DefaultLanguageCode = 'ENU' $mpDefaultLanCode = $MP.DefaultLanguageCode $LanguagePack = New-Object Microsoft.EnterpriseManagement.Configuration.ManagementPackLanguagePack($mp, $mpDefaultLanCode) $DisplayString = New-Object Microsoft.EnterpriseManagement.Configuration.ManagementPackDisplayString($mp, $mpDefaultLanCode) $Displaystring.Name = $DisplayName if ($Description) { $Displaystring.Description = $Description } #Add reference to Microsoft.SystemCenter.Library Write-Verbose "Adding reference for 'Microsoft.SystemCenter.Library'`..." $RefmpCriteria = New-Object Microsoft.EnterpriseManagement.Configuration.ManagementPackCriteria("Name = 'Microsoft.SystemCenter.Library' AND Sealed = 'TRUE'") $RefMP = $MG.GetManagementPacks($RefmpCriteria)[0] If (!$RefMP) { Write-Error "Unable to find the Reference Sealed MP with the name '$ReferenceMPName'." Return $false } else { $RefMPVersion = $RefMP.Version $RefMPKeyToken = $RefMP.KeyToken Write-Verbose "MP 'Microsoft.SystemCenter.Library' Key Token: $RefMPKeyToken" Write-Verbose "MP 'Microsoft.SystemCenter.Library' Version: $RefMPVersion" } $objMPRef = New-Object Microsoft.EnterpriseManagement.Configuration.ManagementPackReference($RefMP) $mp.References.Add('SystemCenter', $objMPRef) #Save the MP Write-Verbose "Saving MP $Name" Try { $mp.verify() $mp.acceptchanges() $MG.ImportManagementPack($mp) $Result = $true Write-Verbose "Management Pack $Name successfully created." } Catch { $Result = $false $mp.RejectChanges() Write-Error "Failed to create Management Pack $Name." } $Result } ######################################################################################################## Function Update-OMGroupDiscovery2 { <# .Notes Author: Tao Yang ( https://blog.tyang.org/ , https://blog.tyang.org/2018/04/18/opsmgrextended-powershell-module-is-now-on-github-and-psgallery/ ) .Synopsis Update the group discovery for a computer group or instance group in OpsMgr. .Description Update the group discovery for a computer group or instance group in OpsMgr using OpsMgr SDK. The group discovery must be defined in an unsealed management pack in order for this function to work. A boolean value $true will be returned if the monitoring object has been successfully added, otherwise, a boolean value of $false is returned if any there are any errors occurred during the process. .Parameter -SDKConnection OpsMgr SDK Connection object (SMA connection or hash table). .Parameter -SDK Management Server name .Parameter -UserName Alternative user name to connect to the management group (optional). .Parameter -Password Alternative password to connect to the management group (optional). .Parameter -GroupName The Group name for computer group or instance group .Parameter -NewConfiguration Computer Principal Name for the unsealed MP of which the override is going to stored. .Parameter -IncreaseMPVersion (boolean) Increase MP version by 0.0.0.1 (Increase revision by 1). .Example # Connect to OpsMgr management group via management server "OpsMgrMS01" and update an instance group by specifying individual parameters: Management Server: "OpsMgrMS01" Username: "domain\SCOM.Admin" Password "password1234" Group Name: Test.Instance.Group New Configuration: @" <RuleId>$MPElement$</RuleId> <GroupInstanceId>$MPElement[Name="Group.Creation.Demo.Demo.Instance.Group"]$</GroupInstanceId> <MembershipRules> <MembershipRule> <MonitoringClass>$MPElement[Name="MSV2D!Microsoft.SystemCenter.VirtualMachineManager.2012.HyperVHost"]$</MonitoringClass> <RelationshipClass>$MPElement[Name="SCIG!Microsoft.SystemCenter.InstanceGroupContainsEntities"]$</RelationshipClass> </MembershipRule> </MembershipRules> "@ $Password = ConvertTo-SecureString -AsPlainText "password1234" -force $NewConfiguration = @' <RuleId>$MPElement$</RuleId> <GroupInstanceId>$MPElement[Name="Test.Instance.Group"]$</GroupInstanceId> <MembershipRules> <MembershipRule> <MonitoringClass>$MPElement[Name="MSV2D!Microsoft.SystemCenter.VirtualMachineManager.2012.HyperVHost"]$</MonitoringClass> <RelationshipClass>$MPElement[Name="SCIG!Microsoft.SystemCenter.InstanceGroupContainsEntities"]$</RelationshipClass> </MembershipRule> </MembershipRules> '@ Update-OMGroupDiscovery -SDK "OpsMgrMS01" -Username "domain\SCOM.Admin" -Password $Password -GroupName "Test.Instance.Group" -NewConfiguration $NewConfiguration .Example # Connect to OpsMgr management group via management server "OpsMgrMS01" and update an computer group by using a SMA Connection Object: OpsMgrSDK Connection (Used in SMA): "OpsMgrSDK_TYANG" Instance Group Name: Test.Computer.Group New Configuration: @' <RuleId>$MPElement$</RuleId> <GroupInstanceId>$MPElement[Name="Test.Computer.Group"]$</GroupInstanceId> <MembershipRules> <MembershipRule Comment="Empty Rule"> <MonitoringClass>$MPElement[Name="Windows!Microsoft.Windows.Computer"]$</MonitoringClass> <RelationshipClass>$MPElement[Name="SystemCenter!Microsoft.SystemCenter.ComputerGroupContainsComputer"]$</RelationshipClass> <IncludeList> <MonitoringObjectId>8d8e7e81-fa51-5248-6f52-3dd8761238ee</MonitoringObjectId> <MonitoringObjectId>1153fce1-9a23-ceee-55c2-bc06bb44aa6b</MonitoringObjectId> </IncludeList> </MembershipRule> </MembershipRules> '@ Increase Management Pack version by 0.0.0.1 $SDKConnection = Get-AutomationConnection -Name OpsMgrSDK_TYANG $NewConfiguration = @' <RuleId>$MPElement$</RuleId> <GroupInstanceId>$MPElement[Name="Test.Computer.Group"]$</GroupInstanceId> <MembershipRules> <MembershipRule Comment="Empty Rule"> <MonitoringClass>$MPElement[Name="Windows!Microsoft.Windows.Computer"]$</MonitoringClass> <RelationshipClass>$MPElement[Name="SystemCenter!Microsoft.SystemCenter.ComputerGroupContainsComputer"]$</RelationshipClass> <IncludeList> <MonitoringObjectId>8d8e7e81-fa51-5248-6f52-3dd8761238ee</MonitoringObjectId> <MonitoringObjectId>1153fce1-9a23-ceee-55c2-bc06bb44aa6b</MonitoringObjectId> </IncludeList> </MembershipRule> </MembershipRules> '@ Update-OMGroupDiscovery -SDKConnection $SDKConnection -GroupName "Test.Instance.Group" -NewConfiguration $NewConfiguration -IncreaseMPVersion $true #> PARAM ( [Parameter(ParameterSetName='SMAConnection',Mandatory=$true,HelpMessage='Please specify the SMA Connection object')][Alias('Connection','c')][System.Object]$SDKConnection, [Parameter(ParameterSetName='IndividualParameter',Mandatory=$true,HelpMessage='Please enter the Management Server name')][Alias('DAS','Server','s')][System.String]$SDK, [Parameter(ParameterSetName='IndividualParameter',Mandatory=$false,HelpMessage='Please enter the user name to connect to the OpsMgr management group')][Alias('u')][System.String]$Username = $null, [Parameter(ParameterSetName='IndividualParameter',Mandatory=$false,HelpMessage='Please enter the password to connect to the OpsMgr management group')][Alias('p')][SecureString]$Password = $null, [Parameter(Mandatory=$true,HelpMessage='Please enter the group name')][Alias('Group')][System.String]$GroupName, [Parameter(Mandatory=$true,HelpMessage='Please enter the new configuration for the group discovery')][Alias('config','Configuration')][System.String]$NewConfiguration, [Parameter(Mandatory=$false,HelpMessage='Increase MP version by 0.0.0.1')][System.Boolean]$IncreaseMPVersion=$false ) #Connect to MG If ($SDKConnection) { Write-Verbose "Connecting to Management Group via SDK $($SDKConnection.ComputerName)`..." $MG = Connect-OMManagementGroup -SDKConnection $SDKConnection $SDK = $SDKConnection.ComputerName $Username = $SDKConnection.UserName $Password= ConvertTo-SecureString -AsPlainText $SDKConnection.Password -force } else { Write-Verbose "Connecting to Management Group via SDK $SDK`..." If ($Username -and $Password) { $MG = Connect-OMManagementGroup -SDK $SDK -UserName $Username -Password $Password } else { $MG = Connect-OMManagementGroup -SDK $SDK } } #Get the group class Write-Verbose "Getting the group '$GroupName'." $GroupClassCriteria = New-Object Microsoft.EnterpriseManagement.Configuration.MonitoringClassCriteria("Name='$GroupName'") $GroupClass = $MG.GetMonitoringClasses($GroupClassCriteria)[0] If ($GroupClass -eq $null) { Write-Error "$GroupName is not found." Return $false } #Check if this monitoring class is actually an instance group or computer group Write-Verbose "Check if the group '$GroupName' is an instance group or a computer group." $GroupBaseTypes = $GroupClass.GetBaseTypes() $bIsGroup = $false Foreach ($item in $GroupBaseTypes) { If ($item.Id.Tostring() -eq '4ce499f1-0298-83fe-7740-7a0fbc8e2449') { Write-Verbose "'$GroupName' is an instance group." $bIsGroup = $true } If ($item.Id.Tostring() -eq '0c363342-717b-5471-3aa5-9de3df073f2a') { Write-Verbose "'$GroupName' is a computer group." $bIsGroup = $true } } If ($bIsGroup -eq $false) { Write-Error "$GroupName is not an instance group or a computer group." Return $false } #Get Group object $GroupObject = $MG.GetMonitoringObjects($GroupClass)[0] $GroupDiscoveries = $GroupObject.GetMonitoringDiscoveries() $iGroupPopDiscoveryCount = 0 $GroupPopDiscovery = $null Foreach ($Discovery in $GroupDiscoveries) { $DiscoveryDS = $Discovery.DataSource #Microsft.SystemCenter.GroupPopulator ID is 488000ef-e20b-1ac4-d3b1-9d679435e1d7 If ($DiscoveryDS.TypeID.Id.ToString() -eq '488000ef-e20b-1ac4-d3b1-9d679435e1d7') { #This data source module is using Microsft.SystemCenter.GroupPopulator $iGroupPopDiscoveryCount = $iGroupPopDiscoveryCount + 1 $GroupPopDiscovery = $Discovery Write-Verbose "Group Populator discovery found: '$($GroupPopDiscovery.Name)'" } } If ($iGroupPopDiscoveryCount.count -eq 0) { Write-Error "No group populator discovery found for $GroupName." Return $false } If ($iGroupPopDiscoveryCount.count -gt 1) { Write-Error "$GroupName has multiple discoveries using Microsft.SystemCenter.GroupPopulator Module type. Unable to continue." Return $false } #Get the MP of where the group populator discovery is defined $GroupPopDiscoveryMP = $GroupPopDiscovery.GetManagementPack() $GroupPopDiscoveryMPName = $GroupPopDiscoveryMP.Name Write-Verbose "The group populator discovery '$($GroupPopDiscovery.Name)' is defined in management pack '$GroupPopDiscoveryMPName'." #Write Error and exit if the group discovery MP is sealed Write-Verbose "Checking if '$GroupPopDiscoveryMPName' MP is sealed." If ($GroupPopDiscoveryMP.sealed -eq $true) { Write-Error "Unable to update the group discovery because it is defined in a sealed MP: '$($GroupPopDiscoveryMP.DisplayName)'." Return $false } else { Write-Verbose "'$GroupPopDiscoveryMPName' MP is unsealed. OK to continue." } #Increase MP version If ($IncreaseMPVersion) { $CurrentVersion = $GroupPopDiscoveryMP.Version.Tostring() $vIncrement = $CurrentVersion.Split('.') $vIncrement[$vIncrement.Length - 1] = ([System.Int32]::Parse($vIncrement[$vIncrement.Length - 1]) + 1).ToString() $NewVersion = ([System.String]::Join('.', $vIncrement)) Write-Verbose "Increasing the group discovery MP version to $NewVersion" $GroupPopDiscoveryMP.Version = $NewVersion } #Update the Group Discovery Data Source configuration Write-verbose "Updating the data source configuration for the group discovery '$($GroupPopDiscovery.Name)'." Try { $GroupPopDiscovery.Datasource.Configuration = $NewConfiguration $GroupPopDiscovery.Status = [Microsoft.EnterpriseManagement.Configuration.ManagementPackElementStatus]::PendingUpdate $GroupPopDiscoveryMP.AcceptChanges() $bGroupUpdated = $true } Catch { Write-Error $_.Exception.InnerException.Message # If the MP update failes, dump the MP so it can be analyzed/debugged. Try { $SubDir = (Join-Path $BackupDir 'UpdateFailure') New-Item -Path $SubDir -ItemType Directory -Verbose -Force $GroupPopDiscoveryMP | Export-SCOMManagementPack -Path $SubDir -Verbose -ErrorAction Stop Write-Verbose "Backup Directory: [$($SubDir)]" } Catch { Throw "Unable to output failed MP content to path: [$($SubDir)]. No action taken. Exiting. Error:`n$_" Return } $bGroupUpdated = $false } $bGroupUpdated } ######################################################################################################## Function Load-SCOMCache { [CmdletBinding(DefaultParameterSetName='Parameter Set 1', SupportsShouldProcess=$false, PositionalBinding=$false, HelpUri = 'https://monitoringguys.com/', ConfirmImpact='Medium')] Param ( # User can include additional MPs (typically from MP files: xml,mp,mpb ) [Microsoft.EnterpriseManagement.Configuration.ManagementPack[]]$ManagementPack, [Parameter(ParameterSetName='Parameter Set 1')] [switch]$LoadClasses, [Parameter(ParameterSetName='Parameter Set 1')] [switch]$LoadRules, [Parameter(ParameterSetName='Parameter Set 1')] [switch]$LoadMonitors, [Parameter(ParameterSetName='Parameter Set 1')] [switch]$LoadDiscoveries, # Will create hash tables for Classes, Rules, Monitors, Discoveries. Will also combine all Rules,Monitors,Discoveries into a hash. [Parameter(ParameterSetName='Parameter Set 2')] [switch]$LoadEverything ) Write-Host "Building cache..." -F Yellow $hashAllWFs = @{} # If MPs are provided, make sure all references are available If ($ManagementPack) { $hashAllMPs = @{} $SealedMPs = Get-SCOMManagementPack | Where-Object -FilterScript {$_.Sealed -eq $True } $CombinedMPs = ($ManagementPack + $SealedMPs) $CombinedMPs | ForEach-Object { Try { $hashAllMPs.Add($_.Name,$_) } Catch { Write-Verbose "Unable to add: $($_.Name), $_" } } ForEach ($Ref in @($ManagementPack.References.Value.Name | Sort-Object -Unique) ) { Try { $hashAllMPs[$Ref] } Catch { ForEach ($item in $ManagementPack) { If ($Ref -in @($ManagementPack.References.Value.Name)){ $InvalidMPName = $ManagementPack.Name } } Throw "Reference MP Name:[$Ref] in provided MP:[$($InvalidMPName)] does not exist in mgmt group or in other provided MPs." } } } If ($LoadClasses -OR $LoadEverything) { # Cache all classes Write-Host "Getting all Classes..." [System.Collections.ArrayList]$AllClasses = @() If ($ManagementPack) { $ManagementPack.GetClasses() | ForEach-Object {$NULL = $AllClasses.Add($_) } } (Get-SCOMClass) | ForEach-Object {$NULL = $AllClasses.Add(([Microsoft.EnterpriseManagement.Configuration.ManagementPackClass]$_)) } Write-Host "$($AllClasses.Count) found. Proceed to build hash object..." $hashAllClasses = @{} $hashAllClassesID = @{} ForEach ($tmpClass in $AllClasses) { Try{ $hashAllClasses.Add($tmpClass.Name, $tmpClass) $hashAllClassesID.Add($tmpClass.ID.GUID,$tmpClass) }Catch{ Write-Verbose "Unable to add $($tmpClass.Name),$($tmpClass.ID.Guid) to hash. $_" } } } If ($LoadMonitors -OR $LoadEverything) { # Cache all monitors Write-Host "Getting all Monitors..." If ($ManagementPack) { $AllMonitors = (($ManagementPack.GetMonitors()) + (Get-SCOMMonitor) ) } Else { $AllMonitors = (Get-SCOMMonitor) } Write-Host "$($AllMonitors.Count) Monitors found. Proceed to build hash object..." $hashAllMonitors = @{} ForEach ($Mon in $AllMonitors) { Try { $hashAllMonitors.Add($Mon.Id.Guid, $Mon) }Catch { Write-Verbose "Unable to add $($Mon.Name),$($Mon.ID.Guid) to hash. $_" } } ForEach ($Key in @($hashAllMonitors.Keys)) { $hashAllWFs.Add($Key,$hashAllMonitors[$Key]) } } If ($LoadRules -OR $LoadEverything) { # Cache all rules Write-Host "Getting all Rules..." If ($ManagementPack) { $AllRules = ( ($ManagementPack.GetRules()) + (Get-SCOMRule) ) } Else { $AllRules = (Get-SCOMRule) } Write-Host "$($AllRules.Count) Rules found. Proceed to build hash object..." $hashAllRules = @{} ForEach ($Rule in $AllRules) { Try{ $hashAllRules.Add($Rule.Id.Guid, $Rule) } Catch { Write-Verbose "Unable to add $($Rule.Name),$($Rule.ID.Guid) to hash. $_" } } ForEach ($Key in @($hashAllRules.Keys)) { $hashAllWFs.Add($Key,$hashAllRules[$Key]) } } If ($LoadDiscoveries -OR $LoadEverything) { # Cache all discoveries Write-Host "Getting all Discoveries..." If ($ManagementPack) { $AllDiscoveries = ( ($ManagementPack.GetDiscoveries()) + (Get-SCOMDiscovery) ) } Else { $AllDiscoveries = (Get-SCOMDiscovery) } Write-Host "$($AllDiscoveries.Count) Discoveries found. Proceed to build hash object..." $hashAllDiscoveries = @{} ForEach ($Disc in $AllDiscoveries) { Try { $hashAllDiscoveries.Add($Disc.Id.Guid, $Disc) } Catch { Write-Verbose "Unable to add $($Disc.Name),$($Disc.ID.Guid) to hash. $_" } } ForEach ($Key in @($hashAllDiscoveries.Keys)) { $hashAllWFs.Add($Key,$hashAllDiscoveries[$Key]) } } }#end Load-SCOMCache ######################################################################################################## Function Import-SCOMPowerShellModule { [CmdletBinding(DefaultParameterSetName='Parameter Set 1', SupportsShouldProcess=$false, PositionalBinding=$false, HelpUri = 'https://monitoringguys.com/', ConfirmImpact='Medium')] Param ( ) Import-Module OperationsManager -Verbose:$VerbosePreference # Try to locate OperationsManager PowerShell module location If (-NOT ((Get-Module OperationsManager).Count) ) { Try { $InstallDir = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\System Center Operations Manager\12\Setup\Powershell\V2").InstallDirectory $SCOMPoshDir = (Join-Path $InstallDir "OperationsManager") Import-module $SCOMPoshDir -ErrorAction Stop -Verbose:$VerbosePreference If (-NOT ((Get-Module OperationsManager).Count) ) { Throw } } Catch { Write-Warning "$(_LINE_): Failed to import OperationsManager module. Exiting" Exit } } } ######################################################################################################## <# .Link http://jdhitsolutions.com/blog/2013/01/ .Inputs Object .Outputs Simulated graph .Notes Version: 1.0? (Tyson: I'm not sure where I found this seemingly early version of this function. However, it seems likely that this is from Jeffery Hicks.) Author? : Jeffery Hicks (http://jdhitsolutions.com/blog) #> Function Out-ConsoleGraph { [CmdletBinding()] Param( [Parameter(Position=0, ValueFromPipeline=$true)] [Object] $Object, [Parameter(Mandatory=$true)] [String] $Property, $Columns ) BEGIN { $Width = $Host.UI.RawUI.BufferSize.Width $Data = @() } PROCESS { # Add all of the objects from the pipeline into an array $Data += $Object } END { # Determine scale of graph Try { $Largest = $Data.$Property | Sort-Object | Select-Object -Last 1 } Catch { Write-Warning "Failed to find property $Property" Return } if ($Largest) { # Add the width of all requested columns to each object $Data = $Data | Select-Object -Property $Columns | ForEach-Object{ $Lengths = @() $Len = 0 $Item = $_ $Columns | ForEach-Object{ if ($Item.$($_)) { $Len += $Item.$($_).ToString().Length } } Add-Member -InputObject $Item -MemberType NoteProperty -Name Length -Value $Len -PassThru $Lengths += $Len } # Determine the available chart space based on width of all requested columns $Sample = $Lengths | Sort-Object -Property Length | Select-Object -Last 1 [Int]$Longest = $Sample.Length + ($Columns.Count * 33) $Available = $Width-$Longest-4 ForEach ($Obj in $Data) { # Set bar length to 0 if it is not a number greater than 0 if ($Obj.$Property -eq '-' -OR $Obj.$Property -eq 0 -or -not $Obj.$Property) { [Int]$Graph = 0 } else { $Graph = (($Obj.$Property) / $Largest) * $Available } # Based on bar size, use a different character to visualize the bar if ($Graph -ge 2) { [String]$G = [char]9608 } elseif ($Graph -gt 0 -AND $Graph -le 1) { [String]$G = [char]9612 $Graph = 1 } # Create the property that will contain the bar $Char = $G * $Graph $Obj | Select-Object -Property $Columns | Add-Member -MemberType NoteProperty -Name Graph -Value $Char -PassThru } # End ForEach } # End if ($Largest) } # End of END block } # End Out-ConsoleGraph ######################################################################################################## Function Remove-OMOverride { <# .Notes Author: Tao Yang ( https://blog.tyang.org/ , https://blog.tyang.org/2018/04/18/opsmgrextended-powershell-module-is-now-on-github-and-psgallery/ ) .Synopsis Remove an override in OpsMgr. .Description Remove an override in OpsMgr using OpsMgr SDK. A boolean value $true will be returned if the override removal has been successful, otherwise, a boolean value of $false is returned if any there are any errors occurred during the removal process. .Parameter -SDKConnection OpsMgr SDK Connection object (SMA connection or hash table). .Parameter -SDK Management Server name .Parameter -UserName Alternative user name to connect to the management group (optional). .Parameter -Password Alternative password to connect to the management group (optional). .Parameter -OverrideName Override name .Parameter -IncreaseMPVersion (boolean) Increase MP version by 0.0.0.1 (Increase revision by 1). .Example # Connect to OpsMgr management group via management server "OpsMgrMS01" and then delete an override with the following properties: Management Server: "OpsMgrMS01" Username: "domain\SCOM.Admin" Password "password1234" Override Name: Test.Performance.Collection.Rule.Interval.Override $Password = ConvertTo-SecureString -AsPlainText "password1234" -force Remove-OMOverride -SDK "OpsMgrMS01" -Username "domain\SCOM.Admin" -Password $Password -OverrideName Test.Performance.Collection.Rule.Interval.Override .Example # Connect to OpsMgr management group via management server "OpsMgrMS01" and then delete an override with the following properties: OpsMgrSDK Connection (Used in SMA): "OpsMgrSDK_TYANG" Override Name: Test.Performance.Collection.Rule.Interval.Override Increase Management Pack version by 0.0.0.1 $SDKConnection = Get-AutomationConnection -Name OpsMgrSDK_TYANG Remove-OMOverride -SDKConnection $SDKConnection -OverrideName Test.Performance.Collection.Rule.Interval.Override -IncreaseMPVersion $true #> [CmdletBinding()] PARAM ( [Parameter(ParameterSetName='SMAConnection',Mandatory=$true,HelpMessage='Please specify the SMA Connection object')][Alias('Connection','c')][System.Object]$SDKConnection, [Parameter(ParameterSetName='IndividualParameter',Mandatory=$true,HelpMessage='Please enter the Management Server name')][Alias('DAS','Server','s')][System.String]$SDK, [Parameter(ParameterSetName='IndividualParameter',Mandatory=$false,HelpMessage='Please enter the user name to connect to the OpsMgr management group')][Alias('u')][System.String]$Username = $null, [Parameter(ParameterSetName='IndividualParameter',Mandatory=$false,HelpMessage='Please enter the password to connect to the OpsMgr management group')][Alias('p')][SecureString]$Password = $null, [Parameter(Mandatory=$true,HelpMessage='Please enter override name')][System.String]$OverrideName, [Parameter(Mandatory=$false,HelpMessage='Increase MP version by 0.0.0.1')][System.Boolean]$IncreaseMPVersion=$false ) #Connect to MG If ($SDKConnection) { Write-Verbose "Connecting to Management Group via SDK $($SDKConnection.ComputerName)`..." $MG = Connect-OMManagementGroup -SDKConnection $SDKConnection $SDK = $SDKConnection.ComputerName $Username = $SDKConnection.Username $Password= ConvertTo-SecureString -AsPlainText $SDKConnection.Password -force } else { Write-Verbose "Connecting to Management Group via SDK $SDK`..." If ($Username -and $Password) { $MG = Connect-OMManagementGroup -SDK $SDK -UserName $Username -Password $Password } else { $MG = Connect-OMManagementGroup -SDK $SDK } } #Get the override Write-Verbose "Getting Override $OverrideName" $strQuery = "Name = '$OverrideName'" $OverrideCriteria = New-Object Microsoft.EnterpriseManagement.Configuration.MonitoringOverrideCriteria($strQuery) $Override = $MG.GetMonitoringOverrides($OverrideCriteria)[0] If (!$Override) { Write-Error "Unable to find the override with name $OverrideName" Return $false } Write-Verbose "Getting the override management pack" $MP = $Override.GetManagementPack() If ($MP.sealed) { Write-Error "Unable to delete the override $overrideName because it is stored in a sealed management pack. Please create another override in a unsealed management pack to override the parameter again." return $false } $MPName = $MP.Name #Deleting the override Write-Verbose "Deleting override $OverrideName" $Override.Status = "PendingDelete" #Increase MP version If ($IncreaseMPVersion) { $CurrentVersion = $MP.Version.Tostring() $vIncrement = $CurrentVersion.Split('.') $vIncrement[$vIncrement.Length - 1] = ([System.Int32]::Parse($vIncrement[$vIncrement.Length - 1]) + 1).ToString() $NewVersion = ([System.String]::Join('.', $vIncrement)) $MP.Version = $NewVersion } #Verify and save the MP Try { $MP.verify() $MP.AcceptChanges() $Result = $true Write-Verbose "Override '$OverrideName' successfully deleted from Management Pack '$MPName'($($MP.Version))." } Catch { $Result = $false Write-Error "Unable to create override $OverrideName in management pack $MPName." $MP.RejectChanges() } $Result } ####################################################################### # Private, DO NOT EXPORT THIS FUNCTION. # This will fix the spelling/case of the override Enabled property value (true|false) Function Set-OverrideEnabledCase { Param ( [string]$ExportPath = 'C:\Temp\UnsealedMPBackup' ) $MPs = Get-SCOMManagementPack | Where-Object {$_.Sealed -eq $false} $today = "UnsealedMPBackup_" + (Get-Date -F yyyyMMdd_HHmmss) $todaySubDir = (Join-Path $ExportPath $today) New-Item $todaySubDir -ItemType Directory -Force -Verbose [int]$globalMPsUpdated=0 [int]$globalproblemsDetected=0 Try{ Write-Host "Attempting backup of unsealed MPs to [ $($todaySubDir) ]" -F Cyan $MPs | Export-SCOMManagementPack -Path $todaySubDir } Catch { Write-Error "Unable to backup unsealed MPs. " } If (-not (Get-ChildItem -Path $todaySubDir -Filter *.xml).Count ){ Write-Host "Unsealed MPs were not backed up. Continue anyway? (Not recommended)" -ForegroundColor Yellow -BackgroundColor Red $choice = '' While ($choice -notmatch 'y|n'){ $choice = (Read-Host "Y/N?").ToLower() } If ($choice -match 'n') { Write-Host "Exiting..."; Return } } Else { Write-Host "`n`nFiles backed up..." -F Green (Get-ChildItem -Path $todaySubDir -Filter *.xml) | Select-Object fullname } Write-Host "Proceed to detect/fix overrides `"Enabled`" property value case (true|false) now..." -F Gray ForEach ($mp in $MPs) { [bool]$updates =$false $ORs = $mp.GetOverrides() ForEach ($or in $ORs){ If ($or.Property -eq 'Enabled'){ Write-Host "Inspecting: $($or.Name), $($or.Property):$($or.Value)" -F Gray # If the Value is not all lower case, fix it If (($or.Value -match '^true$|^false$') -AND (-NOT ($or.Value -cmatch '^true$|^false$')) ){ $or.Value = $or.Value.ToLower() $or.Status = 'PendingUpdate' Write-Host "New Value: $($or.Name), $($or.Property):$($or.Value)" -ForegroundColor Cyan $updates = $true $globalproblemsDetected++ } } } If ($updates ){ Try { Write-Host "Attempt Verify/Accept changes: $($mp.Name), ID:$($mp.ID)" -F Green $mp.verify() $mp.Acceptchanges() $globalMPsUpdated++ }Catch { Write-Error "$($mp.Name), ID:$($mp.ID) Verify/Accept changes failed!" } } }#ForEach mp If ($globalproblemsDetected) { Write-Host "$globalproblemsDetected problems detected. $globalMPsUpdated MPs updated." -F Green } Else { Write-Host "No problems detected. No changes performed." -F Green } } #End Function Set-OverrideEnabledCase ####################################################################### <# .DESCRIPTION Will sanitize a string to comply with allowed characters for either Display Name or ID. .EXAMPLE Clean-SCOMName -FormatType DisplayName -String "This is !@#$%^&*() 1234567890 my new/crazy\random Display Name" This is () 1234567890 my newcrazyrandom Display Name .EXAMPLE Clean-SCOMName -FormatType Id -String "This is !@#$%^&*() 1234567890 my.. new/crazy\random Display Name..." Thisis1234567890my.newcrazyrandomDisplayName .INPUTS [string] .OUTPUTS [string] .NOTES Author: Tyson Paul (https://monitoringguys.com/) Version History: 2020.07.09 - Original #> Function Clean-SCOMName { [CmdletBinding(DefaultParameterSetName='Parameter Set 1', SupportsShouldProcess=$false, PositionalBinding=$false, HelpUri = 'http://www.microsoft.com/', ConfirmImpact='Medium')] [Alias()] [OutputType([String])] Param ( [string]$String, [ValidateSet("ID", "DisplayName")] [string]$FormatType ) Switch ($FormatType) { "ID" { Return ($string -replace '[^a-zA-Z0-9.]', '').Replace('...','.').Replace('..','.').Replace('..','.').Trim('.') } "DisplayName" { Return ($string -replace '[^a-zA-Z0-9. \-()]', '') } Default { Return ($string -replace '[^a-zA-Z0-9.]', '').Replace('...','.').Replace('..','.').Replace('..','.').Trim('.') } } } ####################################################################### ####################################################################### # END PRIVATE ####################################################################### ######################################################################################################## ######################################################################################################## |