I'm not sure if this the right way to do this, and I'm sure someone more clever will speak up but...I use a lot of junctions/reparsepoints in my development here, and I was used to seeing them called out when I typed "dir" from cmd.exe.
(Notice in the screenshot from cmd.exe that the "foo" directory is actually marked <junction>)
In PowerShell when you type Dir, you're getting an Array of System.IO.FileInfo/System.IO.DirectoryInfo objects that are displayed using some default formatting. That default Formatting is a combination of two things, a Type definition and a View definition.
First, there's no "Mode" property on a DirectoryInfo, so how is one being shown? In PowerShell you can "tack on" new properties with Script. This isn't derivation, as it's type extension. Adding to functionality, type-wide (within the context of PowerShell) for any .NET type. So, in C:\program files\Windows PowerShell\v1.0\ there's a file called types.ps1xml that has this little bit of info:
<Type> <Name>System.IO.DirectoryInfo</Name> <Members> <ScriptProperty> <Name>Mode</Name> <GetScriptBlock> here's where the magic happens... </GetScriptBlock> </ScriptProperty> </Members> </Type>
So, I created a personal My.Types.Ps1.xml file in my PSConfiguration folder that looked like this, where 1024 is the value of the [int]([System.IO.FileAttributes]::ReparsePoint) enum and "-band" is "bitwise and."
<Types> <Type> <Name>System.IO.DirectoryInfo</Name> <Members> <ScriptProperty> <Name>ExtMode</Name> <GetScriptBlock> $catr = ""; if ( $this.Attributes -band 1024 ) { $catr += "j" } else { $catr += "-" }; if ( $this.Attributes -band 16 ) { $catr += "d" } else { $catr += "z" }; if ( $this.Attributes -band 32 ) { $catr += "a" } else { $catr += "-" } ; if ( $this.Attributes -band 1 ) { $catr += "r" } else { $catr += "-" } ; if ( $this.Attributes -band 2 ) { $catr += "h" } else { $catr += "-" } ; if ( $this.Attributes -band 4 ) { $catr += "s" } else { $catr += "-" } ; $catr </GetScriptBlock> </ScriptProperty> </Members> </Type> <Type> <Name>System.IO.FileInfo</Name> <Members> <ScriptProperty> <Name>ExtMode</Name> <GetScriptBlock> # Added the extra "-" to make sure things line up when FileInfos and DirectoryInfos are listed together $catr = "-"; if ( $this.Attributes -band 16 ) { $catr += "d" } else { $catr += "-" } ; if ( $this.Attributes -band 32 ) { $catr += "a" } else { $catr += "-" } ; if ( $this.Attributes -band 1 ) { $catr += "r" } else { $catr += "-" } ; if ( $this.Attributes -band 2 ) { $catr += "h" } else { $catr += "-" } ; if ( $this.Attributes -band 4 ) { $catr += "s" } else { $catr += "-" } ; $catr </GetScriptBlock> </ScriptProperty> </Members> </Type></Types>
Then in my Microsoft.PowerShell_profile.ps1 (the file that gets executed every time I start a PowerShell) I added:
$profileTypes = $profile | split-path | join-path -childPath "My.Types.ps1xml"Update-TypeData $profileTypes
Now, I'm not sure how to get dir (alias get-childitem) to use MY ExtMode rather than its own, but I think I'd need to override the default View Definition. It's a little tricky with these scoped XML files, because I originally named my new property "Mode" and was chastised for my efforts:
Microsoft.PowerShell, C:\Documents and Settings\shanselm\My Documents\PSConfiguration\My.Types.ps1xml(39) : Error in type "System.IO.FileInfo": Member "Mode"is already present.
So, I named it "ExtMode." We shall see if there's a better way, until then, this function worked.
function edir{ dir | select ExtMode, LastWriteTime, Length, Name}
and got me this output. Notice the "j" now in the ExtMode column.
If I can't override dir's default view, I probably could also have removed the alias for "dir" and replaced it with my own:
if (test-path alias:\dir) { remove-item -force alias:\dir }set-alias dir edir
but edir is fine for me now.
Scott at DevReach in Bulgaria in October
Developer Stand up Comedy - Coding 4 Fun
TechDays/DevDays Netherlands and Belgium:
Posts by Category Posts by Month
Greatest Hits Dev Tools List