Search code examples
c#powershellpowershell-5.1powershell-7.4

How do I set default values dynamically in binary PowerShell module?


In PowerShell I would write an optional Cmdlet parameter having a dynamically computed default value like this:

[Parameter(Position = 0)][string]$Destination = (Get-Location)

How would I do that when writing a binary PowerShell module?


Solution

  • For computing the caller's current location, see PathIntrinsics, using CurrentFileSystemLocation for the example.

    Problem is that you can't reference PSCmdlet.SessionState on field initialization so what you can do is check if your parameter wasn't assigned in one of the processing methods, for example in EndProcessing here.

    using System.Management.Automation;
    
    [Cmdlet(VerbsDiagnostic.Test, "Command")]
    public sealed class TestCommand : PSCmdlet
    {
        [Parameter(Position = 0)]
        public string? Path { get; set; }
    
        protected override void EndProcessing()
        {
            Path ??= SessionState.Path.CurrentFileSystemLocation.Path;
    
            // do stuff with Path
        }
    }
    

    If you want to do it on field initialization you could use a PowerShell instance hooked to the callers runspace (I personally wouldn't recommend doing this when the approach above is so much simpler):

    using System.Linq;
    using System.Management.Automation;
    
    [Cmdlet(VerbsDiagnostic.Test, "Command")]
    public sealed class TestCommand : PSCmdlet
    {
        [Parameter(Position = 0)]
        public string Path { get; set; } = GetPath();
    
        protected override void EndProcessing()
        {
            // do stuff with Path
            WriteObject(Path);
        }
    
        private static string GetPath()
        {
            using PowerShell ps = PowerShell.Create(RunspaceMode.CurrentRunspace);
            return ps
                .AddScript("$pwd.Path")
                .Invoke<string>()
                .FirstOrDefault();
        }
    }