TheGeekery

The Usual Tech Ramblings

Adding XML Elements Using PowerShell

In a follow-up to my previous post on removing XML elements using PowerShell, I decided to figure out how to add elements using PowerShell. I’m working with the same file from Remote Desktop Manager (RDM) and adding remote management configurations based on DNS checks.

In the enterprise licensed version of RDM you are given the ability to add “remote management” interface details to a host configuration. In our environment, that remote management interface is iLO, and is available from a dedicated IP address, over HTTPS, giving you access to a remote console as well as power management features. RDM handles this with a small tweak to the XML file adding another element under the connection meta information.

The XML that RDM is looking for is like this:

1
2
3
4
5
<Connection>
  <MetaInformation>
    <ServerRemoteManagementUrl>https://hostname-ilo</ServerRemoteManagementUrl>
  </MetaInformation>
</Connection>

I’ve removed most of the information, which you can see in the previous post.

As we’re trying to be careful with the file, we need to first validate the XML has a MetaInformation element, and then an existing ServerRemoteManagementUrl element. If one, or neither, exist, then they get created. Not all hosts have iLO interfaces, such as virtual machines, so we need to verify the presence of a DNS record first, and then only create the entry if it exists.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
$ilo_str = "https://{0}-ilo"
$ilo_host = "{0}-ilo"

[XML]$conns = Get-Content c:\temp\connections.xml

$nodes = $conns.ArrayOfConnection.SelectNodes("Connection[ConnectionType[.='RDPConfigured']]")

if ($nodes -eq $null) {
     continue;
}

$nodes | %{
     $node_name = $_.Name
     $meta = $_.SelectSingleNode("./MetaInformation")
     if ($meta -eq $null) {
          $meta = $conns.CreateElement("MetaInformation")
          $_.AppendChild($meta)
     }

     $ilo = $meta.SelectSingleNode("./ServerRemoteManagementUrl")

     if ($ilo -eq $null) {

          $dns = $null;
          try {
               $dns = [System.Net.Dns]::GetHostAddresses($($ilo_host -f $node_name))
          }
          catch [System.Exception]
          {
            ## Doing Nothing ##
          }

          if ($dns -ne $null) {
               $ilo = $conns.CreateElement("ServerRemoteManagementUrl")
               $ilo.InnerText = $ilo_str -f $node_name
               $meta.AppendChild($ilo)
          }

     }

}

$conns.Save("C:\temp\connections_2.xml")

Again, working with a copy of the original file, I use some crafty XPath queries again to only select connections that are RDP. I then loop through the connections/nodes, and extract the name. Lines 14-18 test for the presence of the MetaInformation element, and create it if it doesn’t exist. Line 20 checks for the ServerRemoteManagementUrl element, if it’s not there, it creates it proceeds with DNS validation.

Lines 24-31 perform a DNS lookup, unfortunately it returns an exception rather than a $null or empty object, so I had to throw in some quick dummy catch code that doesn’t really do anything. If a DNS record is returned it creates the new element, and adds it to the MetaInformation element. For the final step, I saved it to a second file so I could do a comparison between the files to make sure it did as I expected.

One thing to note about adding elements to an XML document is that the CreateElement function (lines 16 and 34) are not executed against the node you are adding the element to, they are executed against the document root. This is so that the element gets all the correct name space information. You then append your element to the existing element.

Comments