See repro below.
As an aside (that will probably become a docs issue): What is the purpose of ConvertTo-Xml? The docs suggest that it is the in-memory counterpart to Export-Clixml, however:
Import-Clixml[pscustomobject] @{ a = [pscustomobject] @{ aa=11; bb=22 } } | ConvertTo-Xml
Should output an [xml] instance that is the serialization of the custom object.
The following error occurs:
ConvertTo-Xml : Unexpected end of file has occurred. The following elements are not closed: Objects.
If you use -As String, you don't get an error, but the XML string output too is missing the closing </Objects> tag.
Removing the 2nd property (bb) from the nested custom object makes the problem go away.
Using [hashtable] instances instead of [pscustomobject]s makes the problem go away.
Export-Clixml does _not_ exhibit the problem.
PowerShell Core 6.2.0-preview.1 on macOS 10.14.1
PowerShell Core 6.2.0-preview.1 on Ubuntu 16.04.5 LTS
PowerShell Core 6.2.0-preview.1 on Microsoft Windows 10 Pro (64-bit; Version 1803, OS Build: 17134.345)
Windows PowerShell v5.1.17134.228 on Microsoft Windows 10 Pro (64-bit; Version 1803, OS Build: 17134.345)
Fails with Windows PowerShell 5.1 so not a regression. Seems specific to nested [PSCustomObject]. Other cases work
get-process | select -first 1 | convertto-xml
Thanks, @SteveL-MSFT. Generally, I only include a Windows PowerShell version in the _Environment data_ section if it _isn't_ a regression (and, conversely, point out if it is). Can you briefly explain the purpose of ConvertTo-Xml with respect to my comments at the top, so I can open doc issues, if/as needed?
@mklement0 I don't know the history of it, but I can make an educated guess. ConvertTo-Xml uses a simplified format that makes it easier to use with other systems that accept XML although it's probably still a bit more abstract than a simple property bag format... Export-CliXml is the same serialization format PowerShell uses for remoting so it's more complete to enable deserialization. Ideally, it seems like we should have had ConvertTo-Xml take a -Format parameter that supported CliXml and other xml formats rather than having this confusion between ExportTo-CliXml and ConvertTo-Xml having incompatible xml formats.
Thanks, @SteveL-MSFT.
other systems that accept XML
So I can suggest improvements to the docs: can you give examples of such other systems?
Are there common real-world scenarios?
I've created a docs issue at https://github.com/PowerShell/PowerShell-Docs/issues/3310.
@mklement0 @SteveL-MSFT this does seem specific to pscustomobject. The following works:
[psobject] @{ a = [psobject] @{ aa=11; bb=22 } } | ConvertTo-Xml
@sdwheeler: Yes, but do note that casting to [psobject] is a virtual no-op, because only the [pscustombject] cast provides the custom-object construction syntactic sugar:
PS> ([psobject] @{ a = [psobject] @{ aa=11; bb=22 } }).GetType().Name
Hashtable # !! [psobject] was effectively ignored.
As an aside: I say _virtual_ no-op, because you do get an extra [psobject] wrapper, though that is _mostly_ invisible - except when it isn't.
In other words: your command is the same as the following, and therefore operates on a hashtable:
@{ a = @{ aa=11; bb=22 } } | ConvertTo-Xml
@mklement0 the "other systems" was purely hypothetical :) In this day and age, it's probably safe to say it's very uncommon to use XML vs JSON. Other than some demos, I've never had to use ConvertTo-Xml myself for any real world scenarios.
Looks like the serializer erroneously decreases the serialization depth when writing PSObject properties:
https://github.com/PowerShell/PowerShell/blob/5d03e1653a7d518715fa3f00587cad6b5c78cc89/src/Microsoft.PowerShell.Commands.Utility/commands/utility/CustomSerialization.cs#L735
This results in nested properties whenever there's more than one.
Removing --depth; seems to solve the problem completely
@IISResetMe perhaps you could submit a PR with tests :)