How To: populate Terminals Favorites xml file from AD (with OU's intact)

Topics: Developer Forum, Project Management Forum, User Forum
Nov 17, 2014 at 8:26 PM
I wrote a script to do this but it won't fit into the 10,000 limit to I'm breaking it up into a couple of posts. I hope this works. I'm not fantastic at PowerShell but this should work for you, I've tested it in two forests so far and it works well.
Here is the first part:
#Script to populate the Terminals Favorite File from AD
#v1.0
#Written by Chris Davis (www.9z.com)


####Edit the following####
#Where do you want the output file to go?
$fav = 'C:\Users\myUsername\Desktop\temp\Favorites.xml'
#What is the DN of the OU where you save your servers?
$baseSearch = 'OU=MyPuterz,DC=myDomain,DC=local'
###You may also want to:
### - Change the RDP properties to your liking. For instance I have NLA turned off for this example.
### - Change your OU or computer filter from * to something that excludes stuff you don't want in here.
###     Or add to your call using a where-object to pull something out. For instance in mine all our
###     failover cluster VCO's and CNO's start with "CL*" so I exclude that. If you don't know how to
###     query AD, two examples would be these. In this first, we only want computers that don't start with U:
###     get-adcomputer -filter {name -notlike "u*"}
###     In this second example I can exclude OU's with ABC123 in the name
###     Get-ADOrganizationalUnit -SearchBase "$baseSearch" -filter * -properties canonicalName,objectguid | Where-Object {$_.canonicalName -notlike "*ABC123*"}
###There are a lot of customizations that can be done, post if you want more examples or help.


#In this section we create the new XML file, then close it back out. I had
#to do it this way to solve certain problems. It can be optomized but I'll get to
#that in the next version.
if (Test-Path $fav) {Remove-Item $fav}
$xmlFile = new-object system.xml.xmltextwriter($fav,$null)
$xmlFile.Formatting = 'Indented'
$xmlFile.Indentation = 1
$xmlFile.IndentChar = "`t"
$xmlFile.WriteStartDocument()
$xmlFile.WriteStartElement('FavoritesFile')
$xmlFile.WriteAttributeString('xmlns:xsd', 'http://www.w3.org/2001/XMLSchema')
$xmlFile.WriteAttributeString('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance')
$xmlFile.WriteAttributeString('FileVerion', '2.0')
$xmlFile.WriteAttributeString('xmlns', 'http://Terminals.codeplex.com')
$xmlFile.WriteEndElement()
$xmlFile.WriteEndDocument()
$xmlFile.Flush()
$xmlFile.Close()

#Now we re-open the XML file (as I mentioned, to solve certain problems this was opened twice)
import-module activedirectory
$xmlFile = [xml](Get-Content $fav)
$dnsroot = get-addomain | select dnsroot
$TopFavorites = $xmlFile.FavoritesFile.AppendChild($xmlFile.CreateElement("Favorites"))
$TopFIGroups = $xmlFile.FavoritesFile.AppendChild($xmlFile.CreateElement("FavoritesInGroups"))
$TopGroups = $xmlFile.FavoritesFile.AppendChild($xmlFile.CreateElement("Groups"))

#get Org Units and populate
$ous = Get-ADOrganizationalUnit -SearchBase "$baseSearch" -filter * -properties canonicalName,objectguid | Sort-Object name | select objectguid, canonicalName, name
foreach ($ou in $ous) {
$myou = "/"+$ou.name
$parentOUCN = $ou.canonicalName -replace $myou, ""
$parentGUID = $ous | where {$_.canonicalName -eq $parentOUCN} | select objectguid
$ouobjectguid = $ou.objectguid
if ($parentOUCN -eq $dnsroot.dnsroot)
    {$parentguidobject = "00000000-0000-0000-0000-000000000000"}
    else
    {$parentguidobject = $parentGUID.objectguid.guid}
$ouname = $ou.name
$newFaveOU = $TopGroups.AppendChild($xmlFile.CreateElement("Group"))
$nothing = $newFaveOU.SetAttribute("id",$ouobjectguid.guid)
$newFaveParent = $newFaveOU.appendChild($xmlFile.CreateElement("Parent"))
$nothing = $newFaveParent.appendChild($xmlFile.createTextNode("$parentguidobject"))
$newFaveName = $newFaveOU.appendChild($xmlFile.CreateElement("Name"))
$nothing = $newFaveName.appendChild($xmlFile.createTextNode("$ouname"))
$newFavInGroups = $TopFIGroups.AppendChild($xmlFile.CreateElement("FavoritesInGroup"))
$nothing = $newFavInGroups.SetAttribute("groupId",$ouobjectguid.guid)
$groupidFavs = $newFavInGroups.appendChild($xmlFile.CreateElement("Favorites"))
$nothing = $groupidFavs.appendChild($xmlFile.CreateElement("guid"))
$xmlFile.save($fav)
}

#get computers from AD
$servers = Get-ADComputer -SearchBase "$baseSearch" -filter * -properties description,canonicalName,objectguid | Sort-Object name | select description,canonicalName,objectguid,name
foreach ($server in $servers) {
$myServer = "/"+$server.name
$parentContainerCN = $server.canonicalName -replace $myServer, ""
$parentContainerGUID = $ous | where {$_.canonicalName -eq $parentContainerCN} | select objectguid
$parentguidobject = $parentContainerGUID.objectguid.guid
$ServerObjectGUID = $server.objectguid
$serverPrettyName = $server.name  #in my case I also added a location to this using an attribute we populated
$serverHostName = $server.name
$ServerNotes = $server.description

$newFavInGrp = $xmlFile.FavoritesFile.FavoritesInGroups.FavoritesInGroup | where {$_.groupid -eq "$parentguidobject"}
$newFavInGrpGUID = $newFavInGrp.favorites.AppendChild($xmlFile.CreateElement("guid"))
$nothing = $newFavInGrpGUID.appendChild($xmlFile.createTextNode("$ServerObjectGUID"))

$newFavorite = $TopFavorites.AppendChild($xmlFile.CreateElement("Favorite"))
$nothing = $newFavorite.SetAttribute("id",$ServerObjectGUID.guid)

$newFavoriteName = $newFavorite.appendChild($xmlFile.CreateElement("Name"))
$nothing = $newFavoriteName.appendChild($xmlFile.createTextNode("$serverPrettyName"))

$newFavoriteProtocol = $newFavorite.appendChild($xmlFile.CreateElement("Protocol"))
$nothing = $newFavoriteProtocol.appendChild($xmlFile.createTextNode("RDP"))

$newFavoritePort = $newFavorite.appendChild($xmlFile.CreateElement("Port"))
$nothing = $newFavoritePort.appendChild($xmlFile.createTextNode("3389"))

$newFavoriteHostName = $newFavorite.appendChild($xmlFile.CreateElement("ServerName"))
$nothing = $newFavoriteHostName.appendChild($xmlFile.createTextNode("$serverHostName"))

$newFavSecurity = $newFavorite.appendChild($xmlFile.CreateElement("Security"))
$nothing = $newFavSecurity.appendChild($xmlFile.CreateElement("EncryptedUserName"))
$nothing = $newFavSecurity.appendChild($xmlFile.CreateElement("EncryptedDomain"))
$nothing = $newFavSecurity.appendChild($xmlFile.CreateElement("EncryptedPassword"))
$nothing = $newFavorite.appendChild($xmlFile.CreateElement("ToolBarIconFile"))

$newFavoriteNewWindow = $newFavorite.appendChild($xmlFile.CreateElement("NewWindow"))
$nothing = $newFavoriteNewWindow.appendChild($xmlFile.createTextNode("false"))

$nothing = $newFavorite.appendChild($xmlFile.CreateElement("DesktopShare"))

$newExecuteBeforeConnect = $newFavorite.appendChild($xmlFile.CreateElement("ExecuteBeforeConnect"))
$newExecuteBeforeConnectExe = $newExecuteBeforeConnect.appendChild($xmlFile.CreateElement("Execute"))
$nothing = $newExecuteBeforeConnectExe.appendChild($xmlFile.createTextNode("false"))
$nothing = $newExecuteBeforeConnect.appendChild($xmlFile.CreateElement("Command"))
$nothing = $newExecuteBeforeConnect.appendChild($xmlFile.CreateElement("CommandArguments"))
$nothing = $newExecuteBeforeConnect.appendChild($xmlFile.CreateElement("InitialDirectory"))
$newWaitForExit = $newExecuteBeforeConnect.appendChild($xmlFile.CreateElement("WaitForExit"))
$nothing = $newWaitForExit.appendChild($xmlFile.createTextNode("false"))

$newFavDisplay = $newFavorite.appendChild($xmlFile.CreateElement("Display"))
$newFavHeight = $newFavDisplay.appendChild($xmlFile.CreateElement("Height"))
$nothing = $newFavHeight.appendChild($xmlFile.createTextNode("600"))
$newFavWidth = $newFavDisplay.appendChild($xmlFile.CreateElement("Width"))
$nothing = $newFavWidth.appendChild($xmlFile.createTextNode("800"))
$newFavDesktopSize = $newFavDisplay.appendChild($xmlFile.CreateElement("DesktopSize"))
$nothing = $newFavDesktopSize.appendChild($xmlFile.createTextNode("FitToWindow"))
$newFavColors = $newFavDisplay.appendChild($xmlFile.CreateElement("Colors"))
$nothing = $newFavColors.appendChild($xmlFile.createTextNode("Bit16"))

$newRDPOptions = $newFavorite.appendChild($xmlFile.CreateElement("RdpOptions"))
$newConnectToConsole = $newRDPOptions.appendChild($xmlFile.CreateElement("ConnectToConsole"))
$nothing = $newConnectToConsole.appendChild($xmlFile.createTextNode("false"))
$newGrabFocusOnConnect = $newRDPOptions.appendChild($xmlFile.CreateElement("GrabFocusOnConnect"))
$nothing = $newGrabFocusOnConnect.appendChild($xmlFile.createTextNode("false"))
$newFullScreen = $newRDPOptions.appendChild($xmlFile.CreateElement("FullScreen"))
$nothing = $newFullScreen.appendChild($xmlFile.createTextNode("false"))
$UserInterface = $newRDPOptions.appendChild($xmlFile.CreateElement("UserInterface"))
$DisableWindowsKey = $UserInterface.appendChild($xmlFile.CreateElement("DisableWindowsKey"))
$nothing = $DisableWindowsKey.appendChild($xmlFile.createTextNode("false"))
$DoubleClickDetect = $UserInterface.appendChild($xmlFile.CreateElement("DoubleClickDetect"))
$nothing = $DoubleClickDetect.appendChild($xmlFile.createTextNode("false"))
$DisplayConnectionBar = $UserInterface.appendChild($xmlFile.CreateElement("DisplayConnectionBar"))
$nothing = $DisplayConnectionBar.appendChild($xmlFile.createTextNode("false"))
$DisableControlAltDelete = $UserInterface.appendChild($xmlFile.CreateElement("DisableControlAltDelete"))
$nothing = $DisableControlAltDelete.appendChild($xmlFile.createTextNode("false"))
$AcceleratorPassthrough = $UserInterface.appendChild($xmlFile.CreateElement("AcceleratorPassthrough"))
$nothing = $AcceleratorPassthrough.appendChild($xmlFile.createTextNode("false"))
$EnableCompression = $UserInterface.appendChild($xmlFile.CreateElement("EnableCompression"))
$nothing = $EnableCompression.appendChild($xmlFile.createTextNode("false"))
$BitmapPeristence = $UserInterface.appendChild($xmlFile.CreateElement("BitmapPeristence"))
$nothing = $BitmapPeristence.appendChild($xmlFile.createTextNode("false"))
Nov 17, 2014 at 8:26 PM
Here is the second part:
$AllowBackgroundInput = $UserInterface.appendChild($xmlFile.CreateElement("AllowBackgroundInput"))
$nothing = $AllowBackgroundInput.appendChild($xmlFile.createTextNode("false"))
$DisableTheming = $UserInterface.appendChild($xmlFile.CreateElement("DisableTheming"))
$nothing = $DisableTheming.appendChild($xmlFile.createTextNode("false"))
$DisableMenuAnimations = $UserInterface.appendChild($xmlFile.CreateElement("DisableMenuAnimations"))
$nothing = $DisableMenuAnimations.appendChild($xmlFile.createTextNode("false"))
$DisableFullWindowDrag = $UserInterface.appendChild($xmlFile.CreateElement("DisableFullWindowDrag"))
$nothing = $DisableFullWindowDrag.appendChild($xmlFile.createTextNode("false"))
$DisableCursorBlinking = $UserInterface.appendChild($xmlFile.CreateElement("DisableCursorBlinking"))
$nothing = $DisableCursorBlinking.appendChild($xmlFile.createTextNode("false"))
$EnableDesktopComposition = $UserInterface.appendChild($xmlFile.CreateElement("EnableDesktopComposition"))
$nothing = $EnableDesktopComposition.appendChild($xmlFile.createTextNode("false"))
$EnableFontSmoothing = $UserInterface.appendChild($xmlFile.CreateElement("EnableFontSmoothing"))
$nothing = $EnableFontSmoothing.appendChild($xmlFile.createTextNode("false"))
$DisableCursorShadow = $UserInterface.appendChild($xmlFile.CreateElement("DisableCursorShadow"))
$nothing = $DisableCursorShadow.appendChild($xmlFile.createTextNode("false"))
$DisableWallPaper = $UserInterface.appendChild($xmlFile.CreateElement("DisableWallPaper"))
$nothing = $DisableWallPaper.appendChild($xmlFile.createTextNode("false"))
$nothing = $UserInterface.appendChild($xmlFile.CreateElement("LoadBalanceInfo"))

$security = $newRDPOptions.appendChild($xmlFile.CreateElement("Security"))
$SecuirtyEnabled = $security.appendChild($xmlFile.CreateElement("Enabled"))
$nothing = $SecuirtyEnabled.appendChild($xmlFile.createTextNode("false"))
$EnableEncryption = $security.appendChild($xmlFile.CreateElement("EnableEncryption"))
$nothing = $EnableEncryption.appendChild($xmlFile.createTextNode("false"))
$EnableTLSAuthentication = $security.appendChild($xmlFile.CreateElement("EnableTLSAuthentication"))
$nothing = $EnableTLSAuthentication.appendChild($xmlFile.createTextNode("false"))
$EnableNLAAuthentication = $security.appendChild($xmlFile.CreateElement("EnableNLAAuthentication"))
$nothing = $EnableNLAAuthentication.appendChild($xmlFile.createTextNode("false"))

$TimeOuts = $newRDPOptions.appendChild($xmlFile.CreateElement("TimeOuts"))
$ShutdownTimeout = $TimeOuts.appendChild($xmlFile.CreateElement("ShutdownTimeout"))
$nothing = $ShutdownTimeout.appendChild($xmlFile.createTextNode("10"))
$OverallTimeout = $TimeOuts.appendChild($xmlFile.CreateElement("OverallTimeout"))
$nothing = $OverallTimeout.appendChild($xmlFile.createTextNode("600"))
$ConnectionTimeout = $TimeOuts.appendChild($xmlFile.CreateElement("ConnectionTimeout"))
$nothing = $ConnectionTimeout.appendChild($xmlFile.createTextNode("600"))
$IdleTimeout = $TimeOuts.appendChild($xmlFile.CreateElement("IdleTimeout"))
$nothing = $IdleTimeout.appendChild($xmlFile.createTextNode("240"))

$Redirect = $newRDPOptions.appendChild($xmlFile.CreateElement("Redirect"))
$Ports = $Redirect.appendChild($xmlFile.CreateElement("Ports"))
$nothing = $Ports.appendChild($xmlFile.createTextNode("false"))
$Printers = $Redirect.appendChild($xmlFile.CreateElement("Printers"))
$nothing = $Printers.appendChild($xmlFile.createTextNode("false"))
$SmartCards = $Redirect.appendChild($xmlFile.CreateElement("SmartCards"))
$nothing = $SmartCards.appendChild($xmlFile.createTextNode("true"))
$Devices = $Redirect.appendChild($xmlFile.CreateElement("Devices"))
$nothing = $Devices.appendChild($xmlFile.createTextNode("false"))
$Sounds = $Redirect.appendChild($xmlFile.CreateElement("Sounds"))
$nothing = $Sounds.appendChild($xmlFile.createTextNode("DontPlay"))
$Clipboard = $Redirect.appendChild($xmlFile.CreateElement("Clipboard"))
$nothing = $Clipboard.appendChild($xmlFile.createTextNode("true"))
$nothing = $Redirect.appendChild($xmlFile.CreateElement("drives"))

$TsGateway = $newRDPOptions.appendChild($xmlFile.CreateElement("TsGateway"))
$UsageMethod = $TsGateway.appendChild($xmlFile.CreateElement("UsageMethod"))
$nothing = $UsageMethod.appendChild($xmlFile.createTextNode("0"))
$CredentialSource = $TsGateway.appendChild($xmlFile.CreateElement("CredentialSource"))
$nothing = $CredentialSource.appendChild($xmlFile.createTextNode("0"))
$SeparateLogin = $TsGateway.appendChild($xmlFile.CreateElement("SeparateLogin"))
$nothing = $SeparateLogin.appendChild($xmlFile.createTextNode("false"))
$nothing = $TsGateway.appendChild($xmlFile.CreateElement("HostName"))
$TSSecurity = $TsGateway.appendChild($xmlFile.CreateElement("Security"))
$nothing = $TSSecurity.appendChild($xmlFile.CreateElement("EncryptedUserName"))
$nothing = $TSSecurity.appendChild($xmlFile.CreateElement("EncryptedDomain"))
$nothing = $TSSecurity.appendChild($xmlFile.CreateElement("EncryptedPassword"))

$FavNotes = $newFavorite.appendChild($xmlFile.CreateElement("Notes"))
$nothing = $FavNotes.appendChild($xmlFile.createTextNode("$ServerNotes"))

$xmlFile.save($fav)

}


#We now open the file a third time to clean up some stuff that got left over
$badXML = ' xmlns=""'
$badguid = "        <guid />"
$dumpXML = Get-Content $fav
$cleanXML = $dumpXML -replace $badXML,""
$cleanXML = $cleanXML -replace $badguid,""
$cleanXML | Foreach {$_.TrimEnd()} | where {$_ -ne ""} | Set-Content $fav
Nov 17, 2014 at 8:30 PM
Ok it looks like it all made it. Just take the two chunks and paste them into a .ps1 or dump them into ISE.
Again as I mentioned, I'm not a ninja at PowerShell so this isn't optimized or terribly clean. It just does the job. I'm happy to help customize the code if you need a specific searchBase in AD or to show you how to put different options into the configuration file it spits out.
Please let me know if there are any issues.
I'll blog the solution on TechNet and at 9z as well.
Hope it helps.
-Chris