So I have been beating my head against the wall for about a day now on this and I am struggling to create a elegant, or working for that matter, solution.
Background
The script I am working on is a universal application installer that we can pair with our application deployment software but also be usable by on-site admins to ensure all applications are always deployed identically and to really simplify the application deployment process overall.To make the configuration files as simple as possible to create, I have went with xml files. Because PowerShell has a fairly suboptimal way to interface with XML files I am importing the configuration file as a PSObject. This works perfectly except when a XML child node is present multiple times which often happens.
Issue
I am trying to get child nodes with identical names to grouped into an Array object. (Example: $Result | Add-Member -MemberType:'NoteProperty' -Name:($tXML.name) -Value:$(Array of PSObjects;) In this case both of the installer xml nodes). The desired result would be something similar to this. I have isolated the Parent Node definition to SystemObject so in the XML below it calls the SystemObject node case twice (once for installer and once for uninstaller) but I can't figure out how to add the child nodes to a functioning array in the desired format.
Example Picture
Function
Function Convert-XMLtoPSObject {
Param (
$XML
)
New-Variable -Name:'Result' -Value:(New-Object -TypeName:'PSCustomObject')
$xml | Get-Member -MemberType:'Property' |
Where-Object {
$_.MemberType -EQ 'Property'
} | ForEach-Object -Process:{
$tXML = $_
Switch -Regex ($_.Definition) {
'^\bstring\b.*$' {
$Result | Add-Member -MemberType:'NoteProperty' -Name:($tXML.Name) -Value:($XML.($tXML.Name))
}
'^\bSystem\.Object\b\[] (?!#comment).*$' {
Write-Host "SystemObject Baby!"
}
'^\bSystem.Xml.XmlElement\b.*$' {
$Result | Add-Member -MemberType:'NoteProperty' -Name:($tXML.Name) -Value:(
Convert-XMLtoPSObject -XML:($XML.($tXML.Name))
)
}
'^\bSystem\.Object\b\[] (#comment).*$' { <# Do Nothing #> }
Default {
Write-Host "Unrecognized Type: $($tXML.Name)='$($tXML.Definition)'"
}
}
}
$Result
}
install.xml
<AppInstall>
<GlobalConfig>
<Directory>{$ConfigDir}</Directory>
<!-- [String] Install flags to append to all installers. -->
<InstallFlags></InstallFlags>
<!-- [ScriptBlock] PowerShell script used to test if this AppInstaller should run. -->
<!-- Note: Should return True of False -->
<FilterScript></FilterScript>
</GlobalConfig>
<Uninstallers>
<Uninstaller>
<ID>0</ID>
<!-- [String] Search String to try to find in registry -->
<SearchString></SearchString>
<!-- [string] How to search for search string. -->
<!-- Options: Simple, Regex, Exact-->
<SearchType></SearchType>
<!-- [String] Attempts to uninstall installers of specific architectures. -->
<!-- Options: x64, x32, Both -->
<Architecture></Architecture>
<!-- [String] Flags to add to uninstaller. -->
<Flags></Flags>
<!-- [Bool] Attempt to extract the uninstaller path. -->
<URLExtraction></URLExtraction>
</Uninstaller>
<Uninstaller>
<ID>0</ID>
<!-- [String] Search String to try to find in registry -->
<SearchString></SearchString>
<!-- [string] How to search for search string. -->
<!-- Options: Simple, Regex, Exact-->
<SearchType></SearchType>
<!-- [String] Attempts to uninstall installers of specific architectures. -->
<!-- Options: x64, x32, Both -->
<Architecture></Architecture>
<!-- [String] Flags to add to uninstaller. -->
<Flags></Flags>
<!-- [Bool] Attempt to extract the uninstaller path. -->
<URLExtraction></URLExtraction>
</Uninstaller>
</Uninstallers>
<Installers>
<Installer>
<!-- [Int] Order in which installer functions will run. -->
<ID>0</ID>
<!-- [String] What OS architecture the installer will run under. -->
<!-- Options: x64, x32, Both -->
<Architecture>x64</Architecture>
<!-- [String] What flags should be added to the installer. -->
<Flags>/QN</Flags>
<!-- [int[]] Comma seperated list of which uninstallers to run and in what order before installing. -->
<RunUninstallers></RunUninstallers>
<!-- [ScriptBlock] PowerShell script used to test if this installer should run. -->
<!-- Note: Should return True of False -->
<FilterScript></FilterScript>
<!-- Directory path to be added to parent GlobalConfig directory -->
<InstallFile>\x64\install.msi</InstallFile>
</Installer>
<Installer>
<!-- [Int] Order in which installer functions will run. -->
<ID>1</ID>
<!-- [String] What OS architecture the installer will run under. -->
<!-- Options: x64, x32, Both -->
<Architecture>x32</Architecture>
<!-- [String] What flags should be added to the installer. -->
<Flags>/QN</Flags>
<!-- [int[]] Comma seperated list of which uninstallers to run and in what order before installing. -->
<RunUninstallers></RunUninstallers>
<!-- [ScriptBlock] PowerShell script used to test if this installer should run. -->
<!-- Note: Should return True of False -->
<FilterScript></FilterScript>
<!-- Directory path to be added to parent GlobalConfig directory -->
<InstallFile>\x32\install.msi</InstallFile>
</Installer>
</Installers>
</AppInstall>
