0

So I have a cmdlet written in c#: Get-LivingCharacter. I want users to use this like Get-LivingCharacter -Name "Bran", but I would like to allow for the list of available characters to change. Maybe today, "Bran" is a valid name to pass in for Get-LivingCharacter, but maybe in the future it will not be. Things happen.

For convenience I want to allow tab-completion of this field. However, I can't seem to get that to work for non-const data sets. Dynamic fields don't even auto-complete the field name, nevermind the value, and I don't know a way to implement this for a non-dynamic field. Conceptually, I could generate a .ps1 file on startup given the current data set, and then load that ps1 as the module, but this feels a bit like killing a pup with a greatsword - lots of overkill. Is there a better option?

Rollie
  • 4,391
  • 3
  • 33
  • 55
  • 1
    Take a look at this article (Dynamic ValidateSet in a Dynamic Parameter): http://blogs.technet.com/b/pstips/archive/2014/06/10/dynamic-validateset-in-a-dynamic-parameter.aspx – Martin Brandl Mar 23 '15 at 14:25
  • 1
    Have you considered using an Enum? You can create a custom enum from a list outside of the function, then cast the parameter as that enum type within the function and you'll get tab completion, and can manipulate the list outside of the function. – mjolinor Mar 23 '15 at 14:52
  • How do you determine what the Living Character set is? Where is that data stored? – Matt Mar 23 '15 at 15:04
  • I knew I had seen something like this question before. Check out [this SO question](http://stackoverflow.com/questions/22993799/populate-parameter-list-from-xml/22997313) for a great write-up by Cookie Monster (with big props to mjolinor for the enum advise there too). The OP there may have accepted my answer, but even I up-voted Cookie's effort. – TheMadTechnician Mar 23 '15 at 23:42

1 Answers1

0

I had already implemented a similar function to the DynamicParam helper function, as reference in the comments. However, tab completion wasn't working. I was writing a minimal reproduction example, when...my tab completion worked.

It turns out, it reproducibly works/breaks based on the inclusion of a WriteDebug statement:

[Cmdlet("Get", "LivingCharacter")]
public class GetLivingCharacter : Cmdlet, IDynamicParameters
{
    protected override void ProcessRecord()
    {
    }

    public object GetDynamicParameters()
    {
        WriteDebug("Getting names"); // Tab completion won't work with this here - comment it out and it works.
        ^^^^^^^^^^

        var chars = new List<String>() { "Bran", "Arya" };            
        var dict = new RuntimeDefinedParameterDictionary();

        var attributes = new Collection<Attribute>
        {
            new ParameterAttribute
            {
                HelpMessage = "Enter a valid open name",
                Mandatory = true
            },
            new ValidateSetAttribute(chars.ToArray()),
        };

        dict.Add("Name", new RuntimeDefinedParameter("Name", typeof(string), attributes));

        return dict;
    }
}

After some digging, the WriteDebug statement is throwing (which I assume is because it can't output while I'm typing). It then recreates the GetLivingCharacter class after I've finished the command to validate. It took a while to find since, because of the issue, I can't write the error to the console, so I had to append to a temp file instead.

Community
  • 1
  • 1
Rollie
  • 4,391
  • 3
  • 33
  • 55