TofuBug
TofuBug

Reputation: 603

In PowerShell why does "casting" to FileInfo set the wrong FullName, Directory, and DirectoryName

I'm noticing a VERY odd behavior in both my PS ISE and PS when I'm getting a FileInfo object by calling

$FileInfo = [System.IO.FileInfo](".\SomeFile.ext")

When I look at its properties the DirectoryName and its related properties all default to the ORIGINAL path that PS opens in.

Here's a copy from my ISE which launches as an administrator with c:\Windows\System32 as the default path

If I run the following code:

$Fileinfo = [System.IO.FileInfo](".\@OpenWithToastLogo.png")  
cd c:\temp  
$Fileinfo2 = [System.IO.FileInfo](".\activation.txt")  
z:  
$Fileinfo3 = [System.IO.FileInfo](".\7za.exe")  
$Fileinfo | fl *
$Fileinfo2 | fl *
$Fileinfo3 | fl *

I get

VersionInfo :
File : C:\WINDOWS\system32\@OpenWithToastLogo.png
InternalName :
OriginalFilename :
FileVersion :
FileDescription :
Product :
ProductVersion :
Debug : False
Patched : False
PreRelease : False
PrivateBuild : False
SpecialBuild : False
Language :
BaseName : @OpenWithToastLogo
Target : {C:\Windows\WinSxS\wow64_microsoft-windows-openwith_31bf3856ad364e35_10.0.10240.16384_none_7f75eaad41c1f239\@OpenWithToastLogo.png,C:\Windows\SysWOW64\@OpenWithToastLogo.png}
LinkType : HardLink
Mode : -a---l
Name : @OpenWithToastLogo.png
Length : 160
DirectoryName : C:\WINDOWS\system32
Directory : C:\WINDOWS\system32
IsReadOnly : False
Exists : True
FullName : C:\WINDOWS\system32\@OpenWithToastLogo.png
Extension : .png CreationTime : 7/10/2015 7:00:32 AM
CreationTimeUtc : 7/10/2015 11:00:32 AM
LastAccessTime : 7/10/2015 7:00:32 AM
LastAccessTimeUtc : 7/10/2015 11:00:32 AM
LastWriteTime : 7/10/2015 7:00:32 AM
LastWriteTimeUtc : 7/10/2015 11:00:32 AM
Attributes : Archive

VersionInfo :
BaseName : activation Target :
LinkType :
Mode : darhsl
Name : activation.txt
Length :
DirectoryName : C:\WINDOWS\system32
Directory : C:\WINDOWS\system32
IsReadOnly : True
Exists : False
FullName : C:\WINDOWS\system32\activation.txt
Extension : .txt
CreationTime : 12/31/1600 7:00:00 PM
CreationTimeUtc : 1/1/1601 12:00:00 AM
LastAccessTime : 12/31/1600 7:00:00 PM
LastAccessTimeUtc : 1/1/1601 12:00:00 AM
LastWriteTime : 12/31/1600 7:00:00 PM
LastWriteTimeUtc : 1/1/1601 12:00:00 AM
Attributes : -1

VersionInfo :
BaseName :
7za Target :
LinkType :
Mode : darhsl
Name : 7za.exe
Length :
DirectoryName : C:\WINDOWS\system32
Directory : C:\WINDOWS\system32
IsReadOnly : True
Exists : False
FullName : C:\WINDOWS\system32\7za.exe
Extension : .exe
CreationTime : 12/31/1600 7:00:00 PM
CreationTimeUtc : 1/1/1601 12:00:00 AM LastAccessTime : 12/31/1600 7:00:00 PM
LastAccessTimeUtc : 1/1/1601 12:00:00 AM
LastWriteTime : 12/31/1600 7:00:00 PM
LastWriteTimeUtc : 1/1/1601 12:00:00 AM
Attributes : -1

With my regular account it defaults to my H:\ path so the same test would have H:\ as the DirectoryName.

And yes, each of these files ONLY exists in the directory it was relative to.

Has anyone seen this before, and do they know a good fix? Using fully qualified of course works but this is for a script that other technicians might run and we're all pretty used to the idea of using relative pathing with PS.

Upvotes: 5

Views: 1780

Answers (1)

TessellatingHeckler
TessellatingHeckler

Reputation: 29033

PowerShell has a notion of your current location. You can see this using the $pwd automatic variable or the Get-Location cmdlet [..]

This path is used by PowerShell to resolve relative paths at the level of the PowerShell API.

[..]

Applications have a notion of the current directory. This is the directory used to resolve relative paths at the level of the Windows API.

How you Get Burned

Your current location may or may not be the same as your current directory.

and

One question that comes up frequently is, “Why does PowerShell not change its [System.Environment]::CurrentDirectory as I navigate around the shell?”

One of the difficult aspects of this comes from the fact that PowerShell supports multiple pipelines of execution. Although it’s not directly exposed yet, users will soon be able to suspend jobs to the background, and other concurrent tasks.

The current directory affects the entire process, so if we change the directory as you navigate around the shell, you risk corrupting the environment of jobs you have running in the background.

When you use filenames in .Net methods, the best practice is to use fully-qualified path names. The Resolve-Path cmdlet makes this easy:

$reader = new-object System.Xml.XmlTextReader (Resolve-Path baseline.xml)

Upvotes: 5

Related Questions