Search code examples
c#powershellmodulepowershell-cmdlet

Powershell C# Extension How to Set the DefaultDisplayProperty when returning data with Write Object


I have created a PowerShell cmdlet in C#:

using System.Management.Automation;
using thosepeskyexternalclasses

[Cmdlet(VerbsCommon.Get, "GetActivity", SupportsTransactions = false)]
public class GetActivity : PSCmdlet
{
    protected override void ProcessRecord()
    {
        base.ProcessRecord();
        // Get the activities
        List<activity> activities = GetActivities();

        WriteObject(activities);

    }
}

The activity object does not contain a name property so when it is returned and displayed it is using the ID Value. This can be resolved by using the following command:

Update-TypeData -TypeName activity -DefaultDisplayProperty otherprop

This has to be done every time I start a new PowerShell session. Is there a way to do the equivalent function when my extension module is loaded?


Solution

  • Add a static ctor to your cmdlet where you can invoke Update-TypeData using a PowerShell instance:

    using System.Collections.Generic;
    using System.Management.Automation;
    using thosepeskyexternalclasses;
    
    [Cmdlet(VerbsCommon.Get, "Activity", SupportsTransactions = false)]
    public sealed class GetActivity : PSCmdlet
    {
        static GetActivity()
        {
            // set the `DefaultDisplayProperty` for the `activity` type the first time this cmdlet is called
            using PowerShell powershell = PowerShell.Create(RunspaceMode.CurrentRunspace);
            powershell
                .AddCommand("Update-TypeData")
                .AddParameters(new Dictionary<string, string>
                {
                    ["TypeName"] = "thosepeskyexternalclasses.activity",
                    ["DefaultDisplayProperty"] = "otherprop" // <- update with actual property name!
                })
                .Invoke();
        }
    
        protected override void ProcessRecord()
        {
            // Get the activities
            List<activity> activities = GetActivities();
            WriteObject(activities);
        }
    }
    

    As mklement0 states in a comment, considering this cmdlet could be part of a binary module, best practice would be to have a *.Types.ps1xml file where you define the default display property. Then you add this file's path to TypesToProcess of your Module Manifest.

    For this specific example, the XML would be something like:

    <?xml version="1.0" encoding="utf-8"?>
    <Types>
      <Type>
        <Name>thosepeskyexternalclasses.activity</Name>
        <Members>
          <MemberSet>
            <Name>PSStandardMembers</Name>
            <Members>
              <NoteProperty>
                <Name>DefaultDisplayProperty</Name>
                <!-- update with actual property name here -->
                <Value>otherprop</Value>
              </NoteProperty>
            </Members>
          </MemberSet>
        </Members>
      </Type>
    </Types>