How do I create a function that accepts multiple argument types from pipeline and command line? How do I create a function that accepts multiple argument types from pipeline and command line? powershell powershell

How do I create a function that accepts multiple argument types from pipeline and command line?


Since your parameter type is string it's coercing the file system info object into a string when you are not using the pipeline { Test-VEnv $_ }. If you call the ToString() method of either a System.IO.FileInfo or System.IO.DirectoryInfo object you'll see this. When you use the pipeline it binds the fullname alias giving you the full path.

You can see what PowerShell is doing to bind the input object using Trace-Command. Here is an example of how to use it:

trace-command -name parameterbinding -expression {(dir C:\)[0] | ? {Test-VEnv $_}} -pshost

Here is the important part of the output:

BIND arg [PerfLogs] to parameter [Path]    Executing DATA GENERATION metadata: [System.Management.Automation.ArgumentTypeConverterAttribute]        result returned from DATA GENERATION: System.String[]    COERCE arg to [System.String[]]        Parameter and arg types the same, no coercion is needed.    BIND arg [System.String[]] to param [Path] SUCCESSFUL

Test-Path does the same thing. Take a look at these three examples:

PS C:\Users\Andy> Test-Path (dir C:\)[0]FalsePS C:\Users\Andy> (dir C:\)[0] | Test-PathTruePS C:\> Test-Path (dir C:\)[0]True
  1. Since my PWD is not C:\ I get FALSE because the DirectoryInfo object is converted to string (ToString()) which only gives the folder name. This is because the pipeline wasn't used.

  2. Since the pipeline is used it works because it is binding to PsPath with this parameter:

    [Parameter(ParameterSetName='LiteralPath', Mandatory=$true, ValueFromPipelineByPropertyName=$true)][Alias('PSPath')][string[]]${LiteralPath},
  3. Since the directory contains the folder the folder's name exists.

You might try the alias PsPath for your binding. This is what Test-Path uses:

param (    [Parameter(Mandatory=$true, Position=0,        ValueFromPipeline=$True,        ValueFromPipelineByPropertyName=$true)]    [Alias('PsPath')]    [String[]] $Path)process {    foreach ($P in $Path) {        Get-Item $p    }}

Some tests:

Set-Location C:\Write-Host 1    Test-VEnv '.\Windows', '.\Program Files'Write-Host 2    Test-VEnv (dir)Write-Host 3    'Windows', 'Program Files' | Test-VEnvWrite-Host 4    dir | Test-VEnv

Output:

1    Directory: C:\Mode                LastWriteTime     Length Name                                                       ----                -------------     ------ ----                                                       d----         3/14/2012   3:41 AM            Windows                                                    d-r--         3/24/2012   7:46 PM            Program Files                                              2d----         2/18/2012   4:32 AM            PerfLogs                                                   d-r--         3/24/2012   7:46 PM            Program Files                                              d-r--         3/25/2012   4:49 PM            Program Files (x86)                                        d----          3/9/2012   9:57 PM            Python27                                                   d-r--          3/4/2012   8:11 PM            Users                                                      d----         3/14/2012   3:41 AM            Windows                                                    -a---          3/4/2012   8:45 PM       1024 .rnd                                                       3d----         3/14/2012   3:41 AM            Windows                                                    d-r--         3/24/2012   7:46 PM            Program Files                                              4d----         2/18/2012   4:32 AM            PerfLogs                                                   d-r--         3/24/2012   7:46 PM            Program Files                                              d-r--         3/25/2012   4:49 PM            Program Files (x86)                                        d----          3/9/2012   9:57 PM            Python27                                                   d-r--          3/4/2012   8:11 PM            Users                                                      d----         3/14/2012   3:41 AM            Windows                                                    -a---          3/4/2012   8:45 PM       1024 .rnd  


@Andy gives some great information specifically addressing points in your question. My answer here is more of a supplement considering the broader implications. It probably only deserves to be a comment but the length and my included image prevent me from posting this as just a comment...

I recently examined the question of pipeline vs. direct input in Powershell with a specific goal towards making these input streams symmetric with respect to all classes of inputs and with respect to what defaults are applied. There are, by my reckoning, six equivalence classes of input to consider:

  • no input
  • null
  • empty
  • scalar
  • list of normal values
  • list of mixed values (i.e. some null or empty)

What one would typically expect when each of these inputs is sent to a function would be this corresponding list:

  • default value
  • null
  • empty
  • scalar
  • list of normal values
  • list of mixed values (i.e. some null or empty)

That is, with no input supplied the default value is used; otherwise the given value is used. This sounds almost trivial, practically a tautology, but there are some subtleties. Consider, for example, what does it mean to supply no input via the pipeline? Is it null or an empty collection? I contend the latter for, among other reasons, it allows the symmetry between streams I mentioned above. Furthermore, how you write both your function signature and your function body makes sometimes surprising impacts on some or all of these input classes with one or the other input stream. Thus, I further contend that there is a lot more to this "trivial" consideration than meets the eye at first glance. So much so that I wrote extensively about it in the articleDown the Rabbit Hole- A Study in PowerShell Pipelines, Functions, and Parameters,published on Simple-Talk.com. Included with the article is a wallchart that shows a table of the six equivalence input classes and what you get for each with different function templates. Here is a thumbnail of the wallchart:

enter image description here


Does it work if you change the type of $path from String[] to [System.IO.DirectoryInfo[]]?