Introduce a PowerShell-aware path-information class for convenient .NET interoperability
See original GitHub issueBest practice answers and documentation often refer to .Net methods for file streaming where it concerns performance, e.g. Processing Large Files. But the .Net implementation differs from native PowerShell behavior were it concerns casting expectations and the current directory:
([io.fileinfo]'.\Test.txt').DirectoryName
C:\WINDOWS\system32
(Get-Item '.\Test.txt').DirectoryName
C:\Users\User\MyScripts
Btw. There is currently no accelerator or initiator for files:
[fileinfo]'.\Test.txt'
InvalidOperation: Unable to find type [fileinfo].
Note that [io.fileinfo]'.\Test.txt'
strips the .\
from every member of the object which means if it is used for a parameter type, you can’t discover anymore that the path was relative (using a condition as e.g. if ($FilePath.Name.StartsWith('.\')) {...
), which means that you can only use a general string
type for this instead.
Using .net (streaming) methods generally require more coding therefore it often ends up in a separate function. As a (spoiled) PowerShell engineer, I would expect to be able to do just this (wishful thinking):
Function Stream-File([FileInfo]$FilePath) {
$Stream = [System.IO.StreamReader]$FilePath
# ...
$Stream.Dispose()
}
Stream-File .\Test.txt
This implies at least two things:
- The (PowerShell)
FileInfo
constructor needs to accept a relative path that is than joined to the current path (Join-Path (Get-Location) '.\Test.txt'
) to prevent it expects the file in theC:\WINDOWS\system32
folder and to be accelerated to resolve the following error:
InvalidOperation: Unable to find type [FileInfo].
- The
[FileInfo]
class should automatically cast to other file classes along withSystem.IO.StreamReader
which current results in the following error:
Cannot convert the “C:\Users\User\MyScripts\Test.txt” value of type “System.IO.FileInfo” to type “System.IO.StreamReader”. InvalidOperation:
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:17 (6 by maintainers)
Top GitHub Comments
This is really a known issue as the .NET methods use the process working directory whereas the PowerShell cmdlets rely on the Runspace location (see https://github.com/PowerShell/PowerShell/issues/3428 and linked issues in there). You can’t really keep them in sync because there’s only 1 process working dir but multiple Runspaces can exist inside a process. Maybe we just need to add some documentation (if there isn’t already) on the best ways to write cmdlets to handle this properly. In my case I usually do the following to handle both
-Path
and-LiteralPath
when calling .NET methodsI’m not sure I agree with having a type accelerator for
FileInfo
specifically, this class is not really something I think we should encourage general use off in PowerShell. Usually the same operations thatFileInfo
(andDirInfo
) are behind the FIleSystem provider included cmdlets likeGet-Item
,Set-Item
, etc. Anyone wishing for these more advanced methods are probably ok with writing the full type name just like any other .NET class without an accelerator.The Engine WG reviewed this issue today. Calling .NET methods with relative paths is a pain point we recognize but we don’t believe there is enough value in adding another type e.g.
[PSPathInfo]
just for this scenario when you can use"$pwd\Test.txt"
. We do suggest submitting an enhancement request to PSSA for a rule that warns about sending relative paths to .NET members.