One of my pet peeves about the PowerShell cmdlets that ship with NAV is the lack of built-in argument completion: the module in question knows exactly which server instances exist (after all, it has a cmdlet that lets you retrieve a list of these instances), but lacks the ability to enumerate the instance names when you specify a -ServerInstance parameter and press the Tab key.

Luckily, PowerShell version 5.0 and up allow custom argument completers to be retrofitted to existing cmdlets. Let’s loop through the cmdlets that have a -ServerInstance parameter, and register an argument completer:

Get-Command `
    -Module Microsoft.Dynamics.Nav.Management `
    -ParameterName ServerInstance | 
        ForEach-Object { 
            Register-ArgumentCompleter `
                -CommandName $_ `
                -ParameterName ServerInstance `
                -ScriptBlock $ScriptBlock 
        }

Before we can do that, of course, we will need to declare a scriptblock that contains the logic for our argument completer. The parameters that the scriptblock receives are defined (and passed upon invocation) by the PowerShell run-time. Our scriptblock may look something like this:

$ScriptBlock = {
    param(
        $commandName, 
        $parameterName, 
        $wordToComplete, 
        $commandAst, 
        $fakeBoundParameter
    )

    Get-NAVServerInstanceName | 
        Where-Object { $_ -like "$wordToComplete*" } |
        ForEach-Object { [System.Management.Automation.CompletionResult]::new($_) } 
    }

where Get-NavServerInstanceName is a function that I declared earlier to extract and normalize the server instance names, like so:

function Get-NAVServerInstanceName {
    Get-NavServerInstance | 
        Select-Object -ExpandProperty ServerInstance |
        ForEach-Object { $_ -replace '^MicrosoftDynamicsNavServer\$', '' }    
}

Here’s the resulting user experience: you can simply tab through the list of server instances, or you can provide a wildcard pattern to further limit the instances that you tab through.