What You See Is Not Always What You Get-Member

powershell3Recently, I was approached by a co-worker to solve an issue they were having in PowerShell.  They wanted to get the full-path of all of the directories in a folder using Get-ChildItem.  By default, Get-ChildItem will display the permissions (Mode), LastWriteTime, Length, and Name columns.  However, the name column only displays the name.  So they asked me if I knew a good way to get the full path.

As administrators and engineers that have been in the industry for 15-20 years, it’s often hard for us to remember that PowerShell isn’t the WYSIWYG (‘What You See Is What You Get’ for you younger engineers. 🙂 ); that we’re moving .NET objects through the pipeline, and while PowerShell displays the most commonly pertinent data in a given command, it’s not everything.  Get-Member is a good way to give us a list of all of the data that’s passed down the pipe from one object to the next, and get the bits that we really need.

So let’s explore!

Get-ChildItem -Path "C:\Windows" -Directory | Get-Member

When you run a command against an object in the pipe, and pipe that to Get-Member, PowerShell looks at the object and displays the properties and methods associated with that object.  For example:

PS C:\> Get-ChildItem -Path "C:\Windows" -Directory | Get-Member

   TypeName: System.IO.DirectoryInfo

Name                      MemberType     Definition
----                      ----------     ---------- 
Mode                      CodeProperty   System.String Mode{get=Mode;}
Create                    Method         void Create(), void Create(System.Security.AccessControl.DirectorySecurity directorySecurity)
CreateObjRef              Method         System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType)
CreateSubdirectory        Method         System.IO.DirectoryInfo CreateSubdirectory(string path), System.IO.DirectoryInfo CreateSubdirector...
Delete                    Method         void Delete(), void Delete(bool recursive)
EnumerateDirectories      Method         System.Collections.Generic.IEnumerable[System.IO.DirectoryInfo] EnumerateDirectories(), System.Col...
EnumerateFiles            Method         System.Collections.Generic.IEnumerable[System.IO.FileInfo] EnumerateFiles(), System.Collections.Ge...
EnumerateFileSystemInfos  Method         System.Collections.Generic.IEnumerable[System.IO.FileSystemInfo] EnumerateFileSystemInfos(), Syste...
Equals                    Method         bool Equals(System.Object obj)
GetAccessControl          Method         System.Security.AccessControl.DirectorySecurity GetAccessControl(), System.Security.AccessControl....
GetDirectories            Method         System.IO.DirectoryInfo[] GetDirectories(), System.IO.DirectoryInfo[] GetDirectories(string search...
GetFiles                  Method         System.IO.FileInfo[] GetFiles(string searchPattern), System.IO.FileInfo[] GetFiles(string searchPa...
GetFileSystemInfos        Method         System.IO.FileSystemInfo[] GetFileSystemInfos(string searchPattern), System.IO.FileSystemInfo[] Ge...
GetHashCode               Method         int GetHashCode()
GetLifetimeService        Method         System.Object GetLifetimeService()
GetObjectData             Method         void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serializati...
GetType                   Method         type GetType()
InitializeLifetimeService Method         System.Object InitializeLifetimeService()
MoveTo                    Method         void MoveTo(string destDirName)
Refresh                   Method         void Refresh()
SetAccessControl          Method         void SetAccessControl(System.Security.AccessControl.DirectorySecurity directorySecurity)
ToString                  Method         string ToString()
PSChildName               NoteProperty   System.String PSChildName=addins
PSDrive                   NoteProperty   System.Management.Automation.PSDriveInfo PSDrive=C
PSIsContainer             NoteProperty   System.Boolean PSIsContainer=True
PSParentPath              NoteProperty   System.String PSParentPath=Microsoft.PowerShell.Core\FileSystem::C:\Windows
PSPath                    NoteProperty   System.String PSPath=Microsoft.PowerShell.Core\FileSystem::C:\Windows\addins
PSProvider                NoteProperty   System.Management.Automation.ProviderInfo PSProvider=Microsoft.PowerShell.Core\FileSystem
Attributes                Property       System.IO.FileAttributes Attributes {get;set;}
CreationTime              Property       datetime CreationTime {get;set;}
CreationTimeUtc           Property       datetime CreationTimeUtc {get;set;}
Exists                    Property       bool Exists {get;}
Extension                 Property       string Extension {get;}
FullName                  Property       string FullName {get;}
LastAccessTime            Property       datetime LastAccessTime {get;set;}
LastAccessTimeUtc         Property       datetime LastAccessTimeUtc {get;set;}
LastWriteTime             Property       datetime LastWriteTime {get;set;}
LastWriteTimeUtc          Property       datetime LastWriteTimeUtc {get;set;}
Name                      Property       string Name {get;}
Parent                    Property       System.IO.DirectoryInfo Parent {get;}
Root                      Property       System.IO.DirectoryInfo Root {get;}
BaseName                  ScriptProperty System.Object BaseName {get=$this.Name;}

That’s a lot of information, and something very promising:

PSPath     NoteProperty     System.String PSPath=Microsoft.PowerShell.Core\FileSystem::C:\Windows\addins

So let’s take a look at this:

PS C:\>Get-ChildItem-Path"C:\Windows"-Directory|Select-ObjectPSPath

PSPath
------
Microsoft.PowerShell.Core\FileSystem::C:\Windows\addins
Microsoft.PowerShell.Core\FileSystem::C:\Windows\AppCompat
Microsoft.PowerShell.Core\FileSystem::C:\Windows\apppatch
Microsoft.PowerShell.Core\FileSystem::C:\Windows\assembly
Microsoft.PowerShell.Core\FileSystem::C:\Windows\AUInstallAgent
Microsoft.PowerShell.Core\FileSystem::C:\Windows\Boot
Microsoft.PowerShell.Core\FileSystem::C:\Windows\CbsTemp
Microsoft.PowerShell.Core\FileSystem::C:\Windows\CCM

Well, that’s not quite what I was looking for.  Let’s look at some of the other properties. FullName looks promising.

PS C:\>Get-ChildItem-Path"C:\Windows"-Directory|Select-ObjectFullName

FullName
--------
C:\Windows\addins
C:\Windows\AppCompat
C:\Windows\apppatch
C:\Windows\assembly
C:\Windows\AUInstallAgent
C:\Windows\Boot
C:\Windows\CbsTemp
C:\Windows\CCM
C:\Windows\ccmcache

Well now.  That looks a lot better!

Let’s try another.

Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration

Returns

ServiceName      DHCPEnabled    Index          Description
-----------      -----------    -----          -----------
Rasl2tp          False          0              WAN Miniport (L2TP)
RasSstp          False          1              WAN Miniport (SSTP)
RasAgileVpn      False          2              WAN Miniport (IKEv2)
PptpMiniport     False          3              WAN Miniport (PPTP)
RasPppoe         False          4              WAN Miniport (PPPOE)
NdisWan          False          5              WAN Miniport (IP)
NdisWan          False          6              WAN Miniport (IPv6)
NdisWan          False          7              WAN Miniport (Network Monitor)
kdnic            True           8              Microsoft Kernel Debug Network Adapter
AsyncMac         False          9              RAS Async Adapter
NETwNe64         True           10             Intel(R) Centrino(R) Ultimate-N 6300 AGN
e1iexpress       True           11             Intel(R) 82579LM Gigabit Network Conne...
BthPan           True           14             Bluetooth Device (Personal Area Network)
vwifimp          True           15             Microsoft Wi-Fi Direct Virtual Adapter
tunnel           False          16             Microsoft ISATAP Adapter
tunnel           False          17             Microsoft ISATAP Adapter
tunnel           False          18             Microsoft Teredo Tunneling Adapter
tunnel           False          19             Microsoft ISATAP Adapter
tunnel           False          20             Microsoft ISATAP Adapter
tunnel           False          21             Microsoft ISATAP Adapter
tunnel           False          22             Microsoft ISATAP Adapter
tunnel           False          23             Microsoft ISATAP Adapter
tunnel           False          24             Microsoft ISATAP Adapter

Good information, sure enough.  But it’s lacking in some key information that you might want to see, such as the IP Address.  So let’s take a look with the following command.

Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration | Get-Member

The results of this are pretty long, so I’m not going to post it here.  But you’ll find a ton of information regarding the adapter configuration including the IP Address, IP Subnet, MAC Address, DNS information, and more.  So with a quick review, you can quickly craft a command to pull some real, pertinent data.  While we’re at it, I only want to see the adapters that have an actual IP Address as well.

PS C:\> Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration | Where-Object IPAddress -NE $null | Select-Object Description,ServiceName,IPAddress,DNSServerSearchOrder

Description                         ServiceName     IPAddress            DNSServerSearchOrder              
-----------                         -----------     ---------            --------------------              
Intel(R) Centrino(R) Ultimate-N ... NETwNe64        {192.168.0.51}   {192.168.0.2, 192.168.0.3}

And there you have it!  Just remember, if you ever feel like you’re looking in the right place, but just can’t seem to find what you’re looking for, Get-Member should be the next place you visit.