I’m trying to write a function that takes multiple arguments, which can come either from the command line, or from the pipeline. The arguments can be strings or directory objects. The idea is that any of the following invocations should work:
Test-VEnv '.\MyPath', '.\AnotherPath'
Test-VEnv (dir)
'MyPath', 'AnotherPath' | Test-VEnv
dir | Test-VEnv
The following code almost works:
function Test-VEnv {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true, Position=0,
ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$true)]
[Alias('FullName')]
[String[]]$Path
)
process {
foreach ($P in $Path) {
...
}
}
}
It handles strings both from the pipeline and the command argument, and handles directory objects from the pipeline (via ValueFromPipelineByPropertyName and the FullName alias). But it doesn’t handle directory objects on the command line, so
dir | Where-Object { Test-VEnv $_ }
fails, as it converts the directory objects to strings, which uses the Name property rather than FullName, and the subsequent code fails.
Can anyone tell me how to achieve what I want?
I am aware that even if I can get this to work, it may not be a particularly good design. But as far as I can tell, it’s how the built in Test-Path works, so I want to try following standard behaviour before I invent my own…
Since your parameter type is
stringit’s coercing the file system info object into a string when you are not using the pipeline{ Test-VEnv $_ }. If you call theToString()method of either aSystem.IO.FileInfoorSystem.IO.DirectoryInfoobject 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:Here is the important part of the output:
Test-Pathdoes the same thing. Take a look at these three examples: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.Since the pipeline is used it works because it is binding to PsPath with this parameter:
Since the directory contains the folder the folder’s name exists.
You might try the alias
PsPathfor your binding. This is whatTest-Pathuses:Some tests:
Output: