Group by Different Properties for Format-Table

Group by Different Properties for Format-Table

  • Comments 1

For my Windows Installer PowerShell Extensions, I've been simplifying some of the use cases and adding additional formats. One thing I wanted to do was display source list information in a table and group either by the attached ProductCode or PatchCode properties. The format-table cmdlet doesn't support multiple properties and doesn't appear to allow you to condition the label. It also seemed that Display.xml, or *.formats.ps1xml files, didn't natively support grouping by multiple property names.

The help topic about_Display.xml hinted at a CustomControl tag, but examples of this and related tags in the default *.formats.ps1xml files offered little insight about their true power. With some help from a simple user-generated XML schema and some trial and error, I was able to display a label with an appropriate value conditionally, such that the following expressions displayed the partial table shown below.

PS> $packages = get-msiproductinfo | ?{ $_.Name -match "Visual Studio" }
PS> $packages += get-msipatchinfo
PS> $packages | get-msisource | format-table -view package

    ProductCode: {388E4B09-3E71-4649-8921-F44A3A2954A7}

Index Type    Path
----- ----    ----
    0 Network m:\c0367ae0d89851da1a\
    1 Network C:\Program Files\Common Files\Microsoft Shared\VSTO\8.0\Micros...
    2 Network m:\3d218a0f32f61beaf41a01459217\

    PatchCode: {6E52C409-0D0D-4B84-AB63-463438D4D33B}

Index Type    Path
----- ----    ----
    0 Network m:\ec91ccc92c8f730e8d87188036\

I accomplished this by using a scriptblock to group, but referencing a CustomControl with multiple ExpressionBinding elements as shown in the partial example below.

<Configuration>
  <Controls>
    <Control>
      <Name>PatchOrProductGrouping</Name>
      <CustomControl>
        <CustomEntries>
          <CustomEntry>
            <CustomItem>
              <Frame>
                <LeftIndent>4</LeftIndent>
                <CustomItem>
                  <ExpressionBinding>
                    <ItemSelectionCondition>
                      <ScriptBlock><![CDATA[$_.ProductCode -ne $null]]></ScriptBlock>
                    </ItemSelectionCondition>
                    <ScriptBlock><![CDATA["ProductCode: " + $_.ProductCode]]></ScriptBlock>
                  </ExpressionBinding>
                  <ExpressionBinding>
                    <ItemSelectionCondition>
                      <ScriptBlock><![CDATA[$_.PatchCode -ne $null]]></ScriptBlock>
                    </ItemSelectionCondition>
                    <ScriptBlock><![CDATA["PatchCode: " + $_.PatchCode]]></ScriptBlock>
                  </ExpressionBinding>
                  <NewLine/>
                </CustomItem>
              </Frame>
            </CustomItem>
          </CustomEntry>
        </CustomEntries>
      </CustomControl>
    </Control>
  </Controls>
  <ViewDefinitions>
    <View>
      <Name>Package</Name>
      <ViewSelectedBy>
        <TypeName>Microsoft.Windows.Installer.PackageSource</TypeName>
      </ViewSelectedBy>
      <GroupBy>
        <ScriptBlock><![CDATA[
          if ($_.ProductCode -ne $null)
          {
            $_.ProductCode
          }
          elseif ($_.PatchCode -ne $null)
          {
            $_.PatchCode
          }
        ]]></ScriptBlock>
        <CustomControlName>PatchOrProductGrouping</CustomControlName>
      </GroupBy>
      <TableControl>
        <!-- Omitted for brevity -->
      </TableControl>
    </View>
  </ViewDefinitions>
</Configuration>
Hopefully this serves as a good example of more powerful features of formatting in PowerShell.
Leave a Comment
  • Please add 5 and 5 and type the answer here:
  • Post