Get-Process Piped to Dir

Did you know that you can pipe the output of Get-Process into dir?  Don’t believe it?  Let me prove it:



PS> Get-Process wi*
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
——-  ——    —–      —– —–   ——     — ———–
     95       4     1080       2892    32     0.30    536 wininit
    126       3     1848       4612    41     1.11    640 winlogon
    676      22    28656      20332   187    40.09   2344 WinMail



PS> Get-Process wi* |dir
    Directory: Microsoft.PowerShell.Core\FileSystem::E:\Windows\system32



Mode                LastWriteTime     Length Name
—-                ————-     —— —-
-a—         8/30/2006   2:21 AM      95232 wininit.exe
-a—         8/30/2006   2:21 AM     306688 winlogon.exe



    Directory: Microsoft.PowerShell.Core\FileSystem::E:\Program Files\Windows Mail



Mode                LastWriteTime     Length Name
—-                ————-     —— —-
-a—         8/29/2006   5:04 PM     120320 WinMail.exe


So you might ask the question: how is the possible?
The answer is easy: code!  🙂


 


 


DIR will operate on anything that has a property called path.  You can validate this with a CSV file:


PS> cat data.csv
Path
c:\autoexec.bat
c:\win*
PS> Import-Csv data.csv |Dir

    Directory: Microsoft.PowerShell.Core\FileSystem::C:\



Mode                LastWriteTime     Length Name
—-                ————-     —— —-
-a—         8/10/2004  11:04 AM          0 autoexec.bat
d—-          9/8/2006   7:13 PM            WINDOWS
d—-         5/11/2006   8:50 AM            winhec
d—-        10/26/2005   8:48 PM            WINNT
d—-          5/9/2006   2:25 PM            winrm



 


 


So all we had to do was to ensure that Process Objects had a PATH property which mapped to the filename of the executable. 


Alas, our friends in the .NET team failed us here – they provided no such Path.  But instead of whining, we just rolled up our sleeves and fixed the problem.  You see this is one of the key scenarios for the Extended Type System.  The people who produce types are just one source of data about the object.  To paraphrase Brandon Sullivan – the community is not a potted plant – it has a role to play here.  You can extend any type with the data you need.  We’ve done that for you for a few objects to show you the way.  Let’s look at the PATH property of the Process object:

PS> Get-Process |Get-Member path
   TypeName: System.Diagnostics.Process


Name MemberType     Definition
—- ———-     ———-
Path ScriptProperty System.Object Path {get=$this.Mainmodule.FileName;}


 


This is a SCRIPTPROPERTY which means “run these scripts to get/set a value” (here we only provide a GETTER).  The variable $THIS is set to the Process object that this property is attached to. 


Thus when a Process object is piped to DIR, the parameter binder sees that DIR can pipeline objects that have a PATH property so it tries to retrieve this from the Process object which runs the script and returns the value.  Its a beatiful thing.


Now you may see some interesting results if the process object does not report a PATH (which is the case for SYSTEM and IDLE).  This binds a NULL to DIR which causes a dir of your current directory.  As such, you might want to always add a where clause


Get-Process |Where {$_.Path} | Dir


So the question is – why would you ever want to do this?  Imagine the case that your system started to act flaky, you might want to know which of the processes was most recently updated.  You can do that this way (Note that this uses MSINCE – a utility that I blogged about earlier today):

PS> Get-Process |Where {$_.Path} |Dir |Sort LastWriteTime |
>> F
ormat-Table fullname,
>> 
@{Label=”Updated (Weeks)”;Expr={MSince$_.LastWriteTime Weeks}} -auto


FullName                                                  Updated (Weeks)
——–                                                  —————
E:\Windows\system32\CCM\CcmExec.exe                                    32
E:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe               4
E:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe               4
E:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe               4
E:\Program Files\Microsoft Office\OFFICE12\OUTLOOK.EXE                  3
E:\Program Files\Windows Defender\MSASCui.exe                           3
E:\Program Files\Windows Mail\WinMail.exe                               3
E:\Windows\system32\SearchIndexer.exe                                   3
E:\Windows\System32\mobsync.exe                                         3
E:\Program Files\Windows Sidebar\sidebar.exe                            3
E:\Windows\System32\snmp.exe                                            3
E:\Program Files\Windows Media Player\wmplayer.exe                      3
E:\Windows\system32\psxss.exe                                           3
E:\Windows\system32\csrss.exe                                           3
E:\Windows\system32\csrss.exe                                           3
E:\Windows\system32\DllHost.exe                                         3
E:\Windows\system32\Dwm.exe                                             3
E:\Windows\Explorer.EXE                                                 3
E:\Program Files\Internet Explorer\ieuser.exe                           3
E:\Program Files\Internet Explorer\iexplore.exe                         3
E:\Program Files\Internet Explorer\IEXPLORE.EXE                         3
E:\Program Files\Internet Explorer\iexplore.exe                         3
E:\Windows\system32\lsass.exe                                           3
E:\Windows\system32\lsm.exe                                             3
E:\Windows\system32\notepad.exe                                         3
E:\Windows\system32\services.exe                                        3
E:\Windows\system32\SLsvc.exe                                           3
E:\Windows\system32\smss.exe                                            3
E:\Windows\System32\spoolsv.exe                                         3
E:\Windows\system32\svchost.exe                                         3
E:\Windows\system32\svchost.exe                                         3
E:\Windows\system32\svchost.exe                                         3
E:\Windows\system32\svchost.exe                                         3
E:\Windows\system32\svchost.exe                                         3
E:\Windows\system32\svchost.exe                                         3
E:\Windows\System32\svchost.exe                                         3
E:\Windows\system32\svchost.exe                                         3
E:\Windows\System32\svchost.exe                                         3
E:\Windows\system32\svchost.exe                                         3
E:\Windows\system32\svchost.exe                                         3
E:\Windows\system32\svchost.exe                                         3
E:\Windows\system32\svchost.exe                                         3
E:\Windows\System32\svchost.exe                                         3
E:\Windows\System32\svchost.exe                                         3
E:\Windows\system32\taskeng.exe                                         3
E:\Windows\system32\taskeng.exe                                         3
E:\Windows\system32\taskeng.exe                                         3
E:\Windows\System32\tcpsvcs.exe                                         3
E:\Windows\system32\wininit.exe                                         3
E:\Windows\system32\winlogon.exe                                        3
E:\Windows\system32\wbem\wmiprvse.exe                                   3
E:\Windows\system32\wuauclt.exe                                         3
C:\systemInternals\autoruns.exe                                         0


 


 


This was pretty interesting because if you look at the dates, it is clear that there are 4 waves of change here.  The latest is the a SystemInternals utility that I installed today.  Then there are a bunch of system processes because I just installed Vista RC1 (3 weeks ago).  Then there is the version of PowerShell (4 weeks ago).  Then there is CcmExec updated 32 weeks ago.  That was curious – I couldn’t image what that could be so I did the following to solve the mystery:


PS> Get-Process CCMEXEC |fl Name,Description,FileVersion,Product
Name        : CcmExec
Description : CCM Executive
FileVersion : 2.50.4160.2000 built by: SMS
Product     : Systems Management Server


Investigate your system – you’ll discover all sorts of cool things.


 


Enjoy!


Jeffrey Snover [MSFT]
Windows PowerShell/Aspen Architect
Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx


 


PSMDTAG:TYPEEXTENSION: ScriptProperty Process Path