For some reason, my program is refusing to work in this scenario:
This is the function:
function Get-ChildItemCustom {
Param(
[Parameter(ValueFromPipeline=$true)]
[System.IO.FileSystemInfo] $item,
[Parameter(ValueFromPipeline=$false)]
[string] $archive_path
)
Process {
Get-ChildItem $item
}
}
I want to be able to use this function just like Get-ChildItem
: input a [System.IO.FileSystemInfo]
object, and get all the children (sorted with some extra criteria that I didn't include here) as output.
This is how I call the function:
Get-ChildItem $parentfolder_path |
Get-ChildItemCustom |
Do-SomethingElse
The error returns explains that the results of Get-ChildItem
(which are verifiably of type [System.IO.FileSystemInfo]
) are being treated as strings.
Cannot convert the "E:\Data\VHG-ITC-Test\New folder\archive" value of type "System.String" to type "System.IO.FileSystemInfo".
The type preceding the parameter was not always there. When $item
did not explicitly have a type, the function would misread the input (supposedly only taking the Name
property as input):
Get-ChildItem : Cannot find path 'C:\Windows\system32\New folder' because it does not exist.
So the function does not seem to be able to accept the object input properly. I want to avoid using strings at all costs, and just move objects around. Have I setup the parameters wrong? What can I do?
The problem isn't exactly with your function, but with the way Get-ChildItem
handles arguments (as Moerwald already suspected in his answer).
When you call Get-ChildItem
with a FileInfo
object as an unnamed argument that argument is passed to the first positional parameter (-Path
), which expects a string array as input, so the object is cast to a string. However, in some situations casting FileInfo
objects to a string expands the FullName
property, while in others it expands just the Name
property (I can't explain how PowerShell decides when to pick which, though). The latter is what's happening in your case. And since Get-ChildItem
sees just a name, not a full path, it's looking for the item in the current working directory, which fails.
There are a number of ways to avoid this issue, one of which Moerwald has already shown. Others are:
using a pipeline for passing $item
to Get-ChildItem
:
function Get-ChildItemCustom {
Param(
[Parameter(ValueFromPipeline=$true)]
[IO.FileSystemInfo]$item,
[Parameter(ValueFromPipeline=$false)]
[string]$archive_path
)
Process {
$item | Get-ChildItem
}
}
passing the full path by mapping the property by name:
function Get-ChildItemCustom {
Param(
[Parameter(
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true
)]
[string[]]$FullName,
[Parameter(ValueFromPipeline=$false)]
[string]$archive_path
)
Process {
Get-ChildItem $FullName
}
}
Personally, I'd prefer the last variant (passing by property name).