Powershell: Export-FormatData only exports first view

Created on 11 Feb 2020  路  7Comments  路  Source: PowerShell/PowerShell

Export-FormatData only exports first view if the InstanceId is set to a blank guid. I am manually creating ExtendedTypeDefinition objects in order to export to *.format.ps1xml. I was able to workaround the issue by exporting the object to clixml and set a random guid and it exported successfully.

image

Steps to reproduce

Describe 'Export-FormatData' {
    It 'Should be able to export multiple views' {
        $listControl = [System.Management.Automation.ListControl]::Create().StartEntry().AddItemProperty('test').AddItemProperty('test2').EndEntry().EndList()
        $tableControl = [System.Management.Automation.TableControl]::Create().StartRowDefinition().AddPropertyColumn('test').AddPropertyColumn('test2').EndRowDefinition().EndTable()

        $listView = [System.Management.Automation.FormatViewDefinition]::new('Default', $listControl)
        $tableView = [System.Management.Automation.FormatViewDefinition]::new('Default', $tableControl)

        $list = New-Object System.Collections.Generic.List[System.Management.Automation.FormatViewDefinition]
        $list.Add($listView)
        $list.Add($tableView)

        $typeDef = [System.Management.Automation.ExtendedTypeDefinition]::new('TestTypeName', $list)
        $typeDef | Export-FormatData -Path C:\temp\test.format.ps1xml
        [xml]$xml = Get-Content C:\temp\test.format.ps1xml
        @($xml.Configuration.ViewDefinitions.View).Count | Should -BeGreaterThan 1
    }
}

Expected behavior

Test should pass

Actual behavior

Describing Export-FormatData
    [-] Should be able to export multiple views 29ms
      at <ScriptBlock>, C:\Temp\format.tests.ps1: line 16
      16:         @($xml.Configuration.ViewDefinitions.View).Count | Should -BeGreaterThan 1
      Expected the actual value to be greater than 1, but got 1.

Environment data

Name                           Value
----                           -----
PSVersion                      7.0.0-rc.2
PSEdition                      Core
GitCommitId                    7.0.0-rc.2
OS                             Microsoft Windows 10.0.18363
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0鈥
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0
Area-Cmdlets-Utility Issue-Bug

Most helpful comment

I'm not familiar with this specific aspect of the code. However, looking at the comments in the code, it seems that InstanceId is expected to be unique to differentiate views with the same name. So it seems that generating a guid where one isn't provided is the right thing to do.

All 7 comments

What *.format.ps1xm contain empty GUIDs? Custom? In the case we should add the check at load time.

The *.format.ps1xml files do not contain a reference to InstanceId. [FormatViewDefinition] has a hidden read-only property InstanceId of type System.Guid and if you manually create a [FormatViewDefinition] object, InstanceId set to all zeros. I don't think that is necessarily a bad thing but Export-FormatData uses that property. If InstanceId is set to all zeros it doesn't properly export all formats.

```powershell
PS C:> $listControl = [System.Management.Automation.ListControl]::Create().StartEntry().AddItemProperty('test').AddItemProperty('test2').EndEntry().EndList()

$tableControl = [System.Management.Automation.TableControl]::Create().StartRowDefinition().AddPropertyColumn('test').AddPropertyColumn('test2').EndRowDefinition().EndTable()

$listView = [System.Management.Automation.FormatViewDefinition]::new('Default', $listControl)
$tableView = [System.Management.Automation.FormatViewDefinition]::new('Default', $tableControl)

$listView.InstanceId
$tableView.InstanceId

Guid

00000000-0000-0000-0000-000000000000
00000000-0000-0000-0000-000000000000
````
I think it has something to do with this section of code.

https://github.com/PowerShell/PowerShell/blob/35c7b7842e7e206f8a6ccc2ab7077a49ad9e7fa6/src/System.Management.Automation/FormatAndOutput/common/FormatXMLWriter.cs#L81-L93

FormatViewDefinition doesn't initialize InstanceId in the code path. I don't know why.

@iSazonov this is the code section you're talking about correct? The public constructor never initializes InstanceId. There is an internal constructor that sets InstanceId. I wonder if there would be an issue setting InstanceId to a new guid in the public constructor.

https://github.com/PowerShell/PowerShell/blob/35c7b7842e7e206f8a6ccc2ab7077a49ad9e7fa6/src/System.Management.Automation/FormatAndOutput/common/DisplayDatabase/displayDescriptionData.cs#L683-L700

https://github.com/PowerShell/PowerShell/blob/35c7b7842e7e206f8a6ccc2ab7077a49ad9e7fa6/src/System.Management.Automation/engine/serialization.cs#L7571-L7578

The public constructor never initializes InstanceId.

This looks like a bug because internal cache uses InstanceId as key.
/cc @SteveL-MSFT Could you please comment?

I'm not familiar with this specific aspect of the code. However, looking at the comments in the code, it seems that InstanceId is expected to be unique to differentiate views with the same name. So it seems that generating a guid where one isn't provided is the right thing to do.

:tada:This issue was addressed in #11896, which has now been successfully released as v7.1.0-preview.1.:tada:

Handy links:

Was this page helpful?
0 / 5 - 0 ratings

Related issues

manofspirit picture manofspirit  路  3Comments

abock picture abock  路  3Comments

garegin16 picture garegin16  路  3Comments

JohnLBevan picture JohnLBevan  路  3Comments

ajensenwaud picture ajensenwaud  路  3Comments