March 15th, 2008

Group by Different Properties for Format-Table

Heath Stewart
Principal Software Engineer

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.

Author

Heath Stewart
Principal Software Engineer

Heath is an application architect and developer, looking to help educate others to learn professional development. Besides designing and developing applications he enjoys writing about intermediate and advanced topics. Heath also consults for deployment packages and scenarios within Microsoft and for external customers.

0 comments

Discussion are closed.

Feedback