0

I have the following powershell script, which I call from the command line:

param(    
    [Parameter(Mandatory = $true)]
    [string]$Name,
    [Parameter(Mandatory = $true)]
    [ValidateScript(
        { $_ -in (Get-ChildItem "..\src\Services" -Directory | Where-Object { $_.Name -ne "obj" }).Name }
    )]
    [ArgumentCompleter(
        {
            param($Command, $Parameter, $WordToComplete, $CommandAst, $FakeBoundParams)
            $ValidValues = (Get-ChildItem "..\src\Services" -Directory | Where-Object { $_.Name -ne "obj" }).Name
            return @($ValidValues) -like "$WordToComplete*"
        }
    )]
    [string]$Project
)

& dotnet ef migrations add $Name `
    --project "..\src\Services\$Project\$Project.Infrastructure" `
    --startup-project "..\src\Services\$Project\$Project.WebApi"

As you can see, ..\src\Services is used in multiple places. The main issue is its use in ValidateScript and ArgumentCompiler.

I have tried solving this by passing in an optional param $PathPrefix = "..\src\Services", but this does not become available in the above-mentioned script decorators, so my argument validation and tab-completion don't work.

Is what I am trying to do possible?

Also is there a name for such functions which encompass an entire file (rather than being defined using function)?

4
  • 1
    you might be able to work around this by using an env: variable, eg: $env:MyScriptPath = "..\src\Services" then your validation and completion use this variable otherwise a more complicated workaround might require defining your own class that takes the path as argument, see last example in stackoverflow.com/a/70061653/15339544 Commented Jun 4 at 13:39
  • @SantiagoSquarzon Thank you. The env variable seems to work for ValidateScript but not ArgumentCompleter - will need to try out the custom class approach Commented Jun 4 at 13:48
  • seems to work fine for me: i.imgur.com/pSXn6HR.png Commented Jun 4 at 13:53
  • @SantiagoSquarzon Ah I see, I was setting that $env in the script file itself Commented Jun 4 at 14:39

1 Answer 1

0

As stated in comments, you should be able to workaround this by setting an environment variable before executing your script, and using that variable as the value for Get-ChildItem in both instances of parameter decorations, validation and completion.

As aside, you should consider using the constructor overload of CompletionResult that will allow you to quote the completion completion text in case the folders have a space.

In summary, your param would become:

param(
    [Parameter(Mandatory = $true)]
    [string] $Name,

    [Parameter(Mandatory = $true)]
    [ValidateScript(
        { $_ -in (Get-ChildItem $env:MyPath -Directory | Where-Object { $_.Name -ne 'obj' }).Name }
    )]
    [ArgumentCompleter(
        {
            param($Command, $Parameter, $WordToComplete, $CommandAst, $FakeBoundParams)

            Get-ChildItem $env:MyPath -Directory |
                Where-Object { $_.Name -ne 'obj' -and $_.Name -like "$WordToComplete*" } |
                ForEach-Object {
                    [System.Management.Automation.CompletionResult]::new(
                        "'$($_.Name)'", $_.Name,
                        [System.Management.Automation.CompletionResultType]::ParameterValue,
                        $_.FullName)
                }
        }
    )]
    [string] $Project
)

Then before running your script you'd first assign a value to the env: variable then invoke your script:

PS /> $env:MyPath = '..\src\Services'
PS /> .\myScript -Name foo -Project <TAB>

Another more complex alternative could be defining your own completion and validation class like the one shown in the last example of this answer that can take a path as argument.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.