Last active
August 26, 2020 07:38
-
-
Save Robert-LTH/459f5bb54dd9ccbd3a144f2467a451ce to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Adds a QueryPanePageDescription to the details of an object in the MEMCM Admin Console | |
.DESCRIPTION | |
Reads the supplied XML-file and finds the node on which it will add a PanePageDescription element. | |
This means that it will add a tab to the details of an object in MEMCM. | |
The supplied example adds a tab which adds a tab to applications which shows a list of devices | |
which has reported that the application has been installed. | |
.EXAMPLE | |
$Params = @{ | |
XMLPath = "$($ENV:SMS_ADMIN_UI_PATH)\..\..\XmlStorage\ConsoleRoot\SoftwareLibraryNode.xml" | |
PageGuid = 'c72ff2f2-3be7-4c81-bc52-60c6430b9efc' | |
QueryGuid = '84f388ed-f2f8-4949-98a7-29bbaacc1450' | |
WQLQueryClass = 'SMS_R_System' | |
WQLQuery = "SELECT SMS_R_System.* FROM SMS_G_System_AppClientState INNER JOIN SMS_R_System ON SMS_G_System_AppClientState.ResourceID = SMS_R_System.ResourceID WHERE SMS_G_System_AppClientState.AppModelName = '##SUB:ModelName##' AND SMS_G_System_AppClientState.ComplianceState = '1'" | |
WQLReturnClass = 'SMS_R_System' | |
RootNodeGuid = 'd2e2cba7-98f5-4d3b-bc2f-b670f0621207' | |
RootQueryGuid = '968164ab-af86-459c-b89e-d3a49c05d367' | |
PageTitle = 'Devices with application' | |
PageDescription = 'Lists all devices that has reported the application as installed' | |
ObjectClass = 'SMS_Application' | |
PropertyListNames = @('Name','ClientVersion','LastLogonTimestamp','LastLogonUserDomain','LastLogonUserName','Obsolete','ResourceNames') | |
} | |
Add-QueryPanePageDescription @Params | |
.NOTES | |
Written by Robert-LTH (https://github.com/robert-lth) | |
Tested on | |
SCCM 1902 | |
SCCM 1906 | |
#> | |
function Add-QueryPanePageDescriptionNode { | |
param( | |
[Parameter(Mandatory=$true)] | |
[ValidateNotNullOrEmpty()] | |
[ValidatePattern("[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}")] | |
[string]$PageGuid, | |
[Parameter(Mandatory=$true)] | |
[ValidateNotNullOrEmpty()] | |
[ValidatePattern("[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}")] | |
[string]$QueryGuid, | |
[Parameter(Mandatory=$true)] | |
[ValidateNotNullOrEmpty()] | |
[string]$WQLQueryClass, | |
[Parameter(Mandatory=$true)] | |
[ValidateNotNullOrEmpty()] | |
[string]$WQLQuery, | |
[Parameter(Mandatory=$true)] | |
[ValidateNotNullOrEmpty()] | |
[string]$WQLReturnClass, | |
[Parameter(Mandatory=$true)] | |
[ValidateNotNullOrEmpty()] | |
[ValidatePattern("[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}")] | |
[string]$RootNodeGuid, | |
[Parameter(Mandatory=$true)] | |
[ValidateNotNullOrEmpty()] | |
[ValidatePattern("[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}")] | |
[string]$RootQueryGuid, | |
[Parameter(Mandatory=$true)] | |
[ValidateNotNullOrEmpty()] | |
[string]$PageTitle, | |
[Parameter(Mandatory=$true)] | |
[ValidateNotNullOrEmpty()] | |
[string]$PageDescription, | |
[Parameter(Mandatory=$true)] | |
[ValidateNotNullOrEmpty()] | |
[string]$ObjectClass, | |
[Parameter(Mandatory=$true)] | |
[ValidateNotNullOrEmpty()] | |
[ValidateCount(1,50)] | |
[string[]]$PropertyListNames, | |
[Parameter(Mandatory=$true)] | |
[ValidateNotNullOrEmpty()] | |
[ValidateScript({Test-Path -PathType Leaf -Path $_})] | |
[string]$XMLPath | |
) | |
try { | |
$XMLDocument = [xml](Get-Content -Path $XMLPath) | |
} | |
catch [System.Management.Automation.RuntimeException] { | |
throw "There was an error processing the xml-content" | |
} | |
# Find the right node to add the pane to | |
$PageList = $XMLDocument.SelectNodes("//RootNodeDescription[@NamespaceGuid='$RootNodeGuid']/Queries/QueryDescription[@NamespaceGuid='$RootQueryGuid']/DetailsPaneDescription[@ObjectClass='$ObjectClass']/PageList") | |
# If the parameters were incorrect it will not find the right nodelist | |
if (($PageList | Measure-Object -Property ChildNodes).Count -le 0) { | |
throw "Could not find the node, verify that the parameters RootNodeGuid,RootQueryGuid and ObjectClass is correct." | |
} | |
# Make sure that it does not exist | |
if ($PageList.PanePageDescription.PageGuid -notcontains $PageGuid) { | |
# Create the node PanePageDescription and set the required attributes | |
$PanePageDescriptionNode = $XMLDocument.CreateElement('PanePageDescription') | |
$PanePageDescriptionNode.SetAttribute('PageGuid',$PageGuid) | |
$PanePageDescriptionNode.SetAttribute('Description',$PageDescription) | |
$PanePageDescriptionNode.SetAttribute('ObjectClass',$ObjectClass) | |
# Create the element PageTitle | |
$PageTitleNode = $XMLDocument.CreateElement('PageTitle') | |
# set the text of the element to the value of $PageTitle | |
$PageTitleNode.InnerText = $PageTitle # | Out-Null | |
# Append the element to the parent element PanePageDescription | |
$PanePageDescriptionNode.AppendChild($PageTitleNode) | Out-Null | |
# Create the element QuerySettingsDescription | |
$QuerySettingsDescription = $XMLDocument.CreateElement('QuerySettingsDescription') | |
# Set the attribute queryclass | |
$QuerySettingsDescription.SetAttribute('QueryClass',$WQLQueryClass) | |
# Create the element Queries | |
$QueriesNode = $XMLDocument.CreateElement('Queries') | |
# Create the element QueryDescription | |
$QueryDescriptionNode = $XMLDocument.CreateElement('QueryDescription') | |
$QueryDescriptionNode.SetAttribute('NamespaceGuid',$QueryGuid) | |
$QueryDescriptionNode.SetAttribute('Type','WQL') | |
$QueryDescriptionNode.SetAttribute('DisplayName','WQL-Query') | |
# Create the element Query | |
$QueryNode = $XMLDocument.CreateElement('Query') | |
# set the text of the element to the value of $WQLQuery | |
$QueryNode.InnerText = $WQLQuery # | Out-Null | |
# Append the element to the parent element Query | |
$QueryDescriptionNode.AppendChild($QueryNode) | Out-Null | |
# Create the element ReturnedClassType | |
$ReturnedClassType = $XMLDocument.CreateElement('ReturnedClassType') | |
# set the text of the element to the value of $WQLQuery | |
$ReturnedClassType.InnerText = $WQLReturnClass # | Out-Null | |
# Append the element to the parent element QueryDescription | |
$QueryDescriptionNode.AppendChild($ReturnedClassType) | Out-Null | |
# Create the element PropertyList | |
$PropertyList = $XMLDocument.CreateElement('PropertyList') | |
# Process the list of property names | |
$PropertyListNames | ForEach-Object { | |
# Create the element PropertyDescription | |
$PropertyDescription = $XMLDocument.CreateElement('PropertyDescription') | |
# Set the attribute Name | |
$PropertyDescription.SetAttribute('Name',$_) | |
# Append the element to the parent element PropertyList | |
$PropertyList.AppendChild($PropertyDescription) | Out-Null | |
} | |
# Append the element to the parent element QueryDescription | |
$QueryDescriptionNode.AppendChild($PropertyList) | Out-Null | |
# Append the element to the parent element Queries | |
$QueriesNode.AppendChild($QueryDescriptionNode) | Out-Null | |
# Append the element to the parent element PanePageDescription | |
$QuerySettingsDescription.AppendChild($QueriesNode) | Out-Null | |
# Append the element to the parent element QuerySettingsDescription | |
$PanePageDescriptionNode.AppendChild($QuerySettingsDescription) | Out-Null | |
# Append the element to the parent element PageList | |
$PageList.AppendChild($PanePageDescriptionNode) | Out-Null | |
# Save the file | |
$XMLDocument.Save($XMLPath) | |
Write-Verbose "Saved '$XMLPath' with the added content." | |
} | |
else { | |
Write-Warning "The supplied GUID already exist." | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment