In this article
Have you ever wanted to simply click a server object and see all of the effective rule and monitor configuration settings in one view? Now you can.
NOTES:
This dashboard isn't perfect. I've seen some weird behavior on occasion. Sometimes the top right widget will update with content from other widgets that exist in other views in other folders. Perhaps the Powershell runspace is sharing scope with other dashboards?. Let me know if you find ways to improve it.
If you select ONLY one computer object (top left), expect to see the entire list of configurations for ALL contained subitems appear in the bottom widget.
This may take a minute to enumerate so be patient. If you select more than one computer you will only see output for the first computer, not multiple computers. This is by design.
Select a subitem (top right) and ONLY the configuration for THAT item will appear in the bottom widget.
If you are not seeing results in the bottom pane, you may have to increase your "PollingInterval" (refresh rate) for your console to give it time to populate the results before re-running the scripts. See here: https://www.bictt.com/blogs/bictt.php/2011/06/01/scom-trick-20-increase-console
Enjoy! Download MP Here: My.Dashboards.xml
Manual Creation Process
1) Create a new Management Pack from the Administration tab. Title it appropriately, something like: "My Dashboards"
2) Once you create the MP, a new folder will appear under your Monitoring tab. Add a new Grid Layout view to the folder.
New -> Dashboard View -> Microsoft -> Grid Layout
Name it "Effective Configuration"
Next.
3 Cells (two on top, one below)
Add the code to each widget:
Finish.
Widget
Title
Code Snippet
Top Left
Group Members: "Windows Computers"
################################################################################################## # ListWindowsComputers # Author: Tyson Paul ( https://blogs.msdn.com/b/tysonpaul/ ) # Date: 7/22/2014 # $class = Get-SCOMClass -Name Microsoft.Windows.Computer $computers = Get-SCOMClassInstance -Class $class $i=1 foreach ($computer in $computers) { $dataObject = $ScriptContext.CreateFromObject($computer, "Id=Id,HealthState=HealthState,DisplayName=DisplayName", $null) $dataObject["Index"]=$($i).ToString("00000") $ScriptContext.ReturnCollection.Add($dataObject) $i++ }
Top Right
Contained Items of Selected Object
# ContainedItemsOfSelectedItem Param($globalSelectedItems) foreach ($globalSelectedItem in $globalSelectedItems) { If ( ($globalSelectedItem["Id"].Length -ge 4 ) ) # Prevent scripts from fighting each other { $globalSelectedItemInstance = Get-SCOMClassInstance -Id $globalSelectedItem["Id"] foreach ($relatedItem in $globalSelectedItemInstance.GetRelatedMonitoringObjects() ) { $dataObject = $ScriptContext.CreateFromObject($relatedItem, "Id=Id,State=HealthState,DisplayName=DisplayName", $null) $dataObject["ParentRelatedObject"] = $globalSelectedItemInstance.DisplayName $ScriptContext.ReturnCollection.Add($dataObject) } } }
Bottom
Effective Configuration of Selected Object (Please wait patiently. This may take a minute...)
################################################################################################### # EffectiveMonitoringConfiguration # Author: Tyson Paul ( ) # Date: 1/14/2015 # # Will recursively find contained instances on a Windows Computer and ouput the effective monitoring configurations/settings to individual output files # Will merge all resulting files into one .csv file, delimited by pipes '|' ################################################################################################### Param($globalSelectedItems) New-Variable -Name StartupVariables -Force -Value (Get-Variable -Scope Global | Select -ExpandProperty Name) ######################################################################################################## Function LogIt ([int]$EventID, [int]$Type=2, [string]$Message="No message specified." , [int]$proceed) { $TimeStamp = (get-date -format "yyyyMMddHHmmssfff") $output = @" Message: $Message "@ If ($proceed -gt 1) { $output += @" ThisScript: EffectiveMonitoringConfiguration.ps1 TimeStamp: $TimeStamp Any Errors: $error "@ } If ($proceed) { $oEvent = New-Object -comObject "MOM.ScriptAPI" $oEvent.LogScriptEvent("$ThisScript",$EventID,$Type,$output) } } #endregion Function ##################################################################################################### # Function MergeFiles # Will find .csv files and merge them together. Function MergeFiles{ Param( [string]$strTargetFolderPath ) $strOutputFile = Join-Path $Env:TEMP "MergedFile.csv" If (Test-Path $strOutputFile) { Remove-Item -Path $strOutputFile } If (Test-Path $strOutputFile) { $Message = "Cannot remove $strOutputFile and therefore cannot generate merged output file. Remove this file first: $strOutputFile , Exiting. " LogIt -EventID 9999 -Message $Message -Type $Critical -Proceed $WriteToEventLog Exit } If (!($strTargetFolderPath)){ $Message = "No input file folder path specified ! Exiting. " LogIt -EventID 9999 -Message $Message -Type $Critical -Proceed $WriteToEventLog Exit } Get-ChildItem -Filter "*.csv" -Path $strTargetFolderPath | ForEach { $intThisHeaderLength = (Get-Content $_.FullName)[0].Length If ($intThisHeaderLength -gt $intLongestHeaderLength) { $objLongestHeaderFile = $_ $intLongestHeaderLength = $intThisHeaderLength } } Get-Content $objLongestHeaderFile.FullName | Set-Content -Path $strOutputFile -Force Get-ChildItem -Path $strTargetFolderPath -Filter *.csv | ForEach { If( ( $_.FullName -eq $objLongestHeaderFile.FullName ) -or ($_.FullName -eq $strOutputFile) ){ #Skip File } Else { (Get-Content $_.FullName | Select -Skip 1).Replace("`0",'') | Out-File -FilePath $strOutputFile -Append -Encoding UTF8 $i++ } } Return $strOutputFile } # EndFunction ################################################################################################### Function Cleanup () { $ErrorActionPreference = "SilentlyContinue" #Depending on when this is called, some variables may not be initialized and clearing could throw benign error. Supress. #Cleanup Get-Variable | Where-Object { $StartupVariables -notcontains $_.Name } | % { Remove-Variable -Name "$($_.Name)" -Force -Scope 1 } } ######################################################################################################## # -------------------------------------------------------------------------------------------------------------------------------------------------------- $WriteToEventLog=0 #Set to 1 or 2 to start logging [int]$info=0 [int]$critical=1 [int]$warning=2 $TempOutputFolder= Join-Path $Env:Temp "EffectiveConfig_$(Get-Random)" Get-ChildItem $Env:Temp -Filter "EffectiveConfig_*" | Remove-Item -Recurse $i=1 If (!(Test-Path $TempOutputFolder)) { new-item -ItemType Directory -Path $TempOutputFolder} If (!(Test-Path $TempOutputFolder)) { LogIt -EventID 9999 -Message $Message -Type $Critical -Proceed $WriteToEventLog Exit } #ForEach ($globalSelectedItem in $globalSelectedItems) #{ $globalSelectedItem = $globalSelectedItems | Select -First 1 $globalSelectedItemInstance = Get-SCOMClassInstance -Id $globalSelectedItem["Id"] If ($globalSelectedItemInstance.Fullname -like "Microsoft.Windows.Computer:*") { $RelatedObjects = $globalSelectedItemInstance.GetRelatedMonitoringObjects() } Else { $RelatedObjects = $globalSelectedItemInstance } $RelatedObjects | ForEach ` { $DN = (($($_.DisplayName).Replace(':','_')).Replace('/','_')).Replace('\','_') $path= (Join-Path $TempOutputFolder "($($_.Path))_$($DN).csv" ) Export-SCOMEffectiveMonitoringConfiguration -Instance $_ -Path $path $i++ } #} $strMergedFilePath = MergeFiles -strTargetFolderPath $TempOutputFolder $Headers = @() $Headers= (Get-Content $strMergedFilePath | Select -First 1).Split('|') $FileContents = (Get-Content $strMergedFilePath | Select -Skip 1 ).Replace("`0",'') $r=1 ForEach ($Row in $FileContents) { If ($Row.Length -le 1) { Continue; } $c=0 $arrRow = @() $arrRow = $Row.Split('|') $dataObject = $ScriptContext.CreateInstance("xsd://foo!bar/baz") $dataObject["Id"] = $r.ToString("0000") $dataObject["Row"] = $r.ToString("0000") ForEach ($Column in $Headers) { If ( ($arrRow[$c] -eq '') -or ($arrRow[$c] -eq ' ') ) { $arrRow[$c] = 'N/A' } $dataObject["$Column ($c)"] = "$($arrRow[$c])" $c++ } $r++ $ScriptContext.ReturnCollection.Add($dataObject) } LogIt -EventID 9998 -Message "Errors: $Error" -Type $Warning -Proceed $WriteToEventLog Remove-Item $TempOutputFolder -Force -Recurse #Cleanup temp folder/files Cleanup
Page History:
2015.1.14: Updated script (EffectiveMonitoringConfiguration) to make Column names unique